游戲性編程是指通過一系列游戲系統將游戲想法變成現實的過程。
本次的簡例以NPC設計為主。
通常在進行腳本設計前,對NPC的屬性進行基本的添加和設定,諸如動畫系統、物理系統等等。
1.動畫系統
添加Animator組件,綁定骨骼。
創建Animator Controller文件,將之添加到組件的Controller部分。
打開Controller,考慮動畫組件的主體需要實現什么功能。
以此例的NPC為例,需要實現他的移動功能。
所以在Controller中添加新的混合樹命名為Locomotion(移動)。
打開混合樹,為其添加三種不同的運動狀態(空閑、走路、奔跑),并綁定相應的動畫文件。
調整三個狀態之間的數值階段,初始為0:0.5:1,調整為0:1:8。
(這里的意義在于更流暢的移動體驗,休閑到走路快速的過渡,走路到奔跑則需要速度到達一定閾值后才能切換。)
備注:
取消勾選Autonate Thresholds后,可以更改數值。
parameter是用于腳本中調用setFloat方法中的參數名,從而在動畫間不斷的切換。
【2】Player腳本
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerMovement : MonoBehaviour
{public float moveSpeed;private Vector3 moveInput;private Vector3 moveVelocity;private Rigidbody rd;private Camera mainCamera;private Animator animator;// Start is called before the first frame updatevoid Start(){rd = GetComponent<Rigidbody>();mainCamera = Camera.main;animator = GetComponent<Animator>();}// Update is called once per framevoid Update(){float lh = Input.GetAxis("Horizontal");//輸入的是左右,即X軸數據,對應著AD鍵位。float lv = Input.GetAxis("Vertical");//輸入的是上下,即Z軸的數據,對應著WS鍵位。
moveInput =new Vector3(lh,0f,lv);//一個即時的向量,當無輸入時是零向量。//在Unity中,人物面朝的方向是藍軸,即Z軸;沿著人物雙手方向的橫軸是紅軸,即X軸;||而沿著人物垂心的是綠軸,即Y軸。Vector3 cameraForword = mainCamera.transform.forward;//主相機在沿著z軸的矢量位置和方向
cameraForword.y = 0;Quaternion s = Quaternion.FromToRotation(Vector3.forward, cameraForword);//這個四元素包含了(0,0,1)到cameraForword的旋轉信息
Vector3 lookToward = s * moveInput;//四元數和向量相乘表示這個向量按照這個四元數進行旋轉之后得到的新的向量。if (moveInput.sqrMagnitude>0){Ray ray = new Ray(transform.position,lookToward);//transform.position為該腳本對應的對象的位置
transform.LookAt(ray.GetPoint(1));//transform.LookAt:旋轉自身,使得當前對象的正z軸指向目標對象target所在的位置(使對象朝向目標點)//ray.GetPoint(1):獲取一個沿著向量方向距離X的點
}moveVelocity = transform.forward*moveSpeed* moveInput.sqrMagnitude;//transform.forward給的是人物坐標軸Z軸的矢量方向,即面朝的方向//(自動對物體旋轉值算出前進方向向量的變量,vector3.forward則不計算旋轉值,所以vector3.forward固定為(0,0,1))//moveVector3.sqrMagnitude返回是坐標軸輸入矢量的平方長度的Float數值,用于控制速度,當無輸入時,速度為0。
Aniamting();}void FixedUpdate(){rd.velocity = moveVelocity;}void Aniamting(){animator.SetFloat("Blend",rd.velocity.magnitude);//調用animator.SetFloat方法,可以設置混合樹中的參數數值,參數名字以自定義的參數名為準
}
}
?【3】scriptableobject(Unity中用于處理序列化的結構)
一個允許你存儲大量獨立于腳本實例的共享數據的類。
目的是通過避免對值進行復制而減少內存的開銷。
定義了一個繼承自ScriptableObject的類,你可以使用CreateAssetMenu?attribute用你的類創建自定義assets。
下面為實例:
Player加載的類
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CharacterStats : MonoBehaviour
{//Stats:一個統計玩家數據的類#region MyRegion//#region 是 C# 預處理器指令。 #region 是一個分塊預處理命令,它主要是用于編輯器代碼的分塊,在編譯時會被自動刪除。//#region 在使用 Visual Studio 代碼編輯器的大綱顯示功能時指定可展開或折疊的代碼塊。有助于代碼的整潔。//
public static CharacterStats instance;void Awake(){instance = this;//傳遞自身的地址}#endregionpublic int MaxHealth = 100;public int CurrentHealth { get; private set; }//可以公共獲取,但只能在該類中設置。void Start(){CurrentHealth = MaxHealth;}public void takeDamage(int damage){CurrentHealth -= damage;if (CurrentHealth <= 0){Dead();}}public void TreatHealth(int treat){print("treat:"+treat);CurrentHealth += treat;print(CurrentHealth);if (CurrentHealth >= 100){print("你恢復了健康");}}public void Dead(){print("You Dead");}}
互動對象體加載的類:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ItemPickUp : Interacrable
{//繼承自Interacrable類(含有與環境互動的代碼)public Itemss item;CharacterStats charStatss=new CharacterStats();public override void Interact()//重寫了父類的方法,并搭載的自己的內容{base.Interact();PickUp();}void PickUp(){item.Use();//這里使用的派生類的基類,但實際上傳遞的是根據Item基類自定義的assets。
Destroy(gameObject);}
}
以下是相關的類,并未直接加載到對象上:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[CreateAssetMenu(fileName = " NewItems",menuName = "Inventory/Item")]public class Itemss : ScriptableObject
{//創建assets的基類new public string name = "Item";public Sprite icon = null;public virtual void Use(){}
}
?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Health Potion",menuName = "Inventory/Item/Health Potion")]
public class HealthPotion : Itemss
{//繼承自Item類的子類,是assets新的藍本。public int HealthModifity;private CharacterStats charStats;void Start(){charStats=CharacterStats.instance;}public override void Use(){base.Use();ApplyEffect();}void ApplyEffect(){CharacterStats.instance.TreatHealth(HealthModifity);//傳遞了玩家參數類的方法。
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Interacrable : MonoBehaviour
{//包含玩家與環境互動的類public bool interacting = false;private Renderer rend;public Material[] materials;void Start(){rend = GetComponent<Renderer>();rend.enabled=true;//啟用渲染器,使渲染的對象可見rend.sharedMaterial = materials[0];//Renderer.sharedMaterial:修改模型材質的顏色,或者是修改材質Shader的一些屬性。//(此方法使用的材料是共享的材料,內存中只有一份,不建議對材料做修改)
}void Update(){if (interacting&&Input.GetKeyDown(KeyCode.Alpha1)){Interact();}if (interacting){rend.sharedMaterial = materials[1];}else{rend.sharedMaterial = materials[0];}}public virtual void Interact(){//虛方法,子類可加Override進行重寫,虛方法本身有方法體。
Destroy(gameObject);}void OnTriggerEnter(Collider other){if (other.gameObject.tag == "Player"){interacting = true;}}void OnTriggerExit(Collider other){if (other.gameObject.tag == "Player"){interacting = false;}}
}
?