Unity(一)Unity脚本程序开发

最近实验室有AR的项目,需要用Unity进行开发,一边学习一边把知识总结下来。在开始项目之前讨论过项目的技术方案,用Unity开发还是用Unreal开发,本人在两种游戏引擎上都有过初步的接触,认为Unreal作为后起之秀确实在某种程度上强于Unity,比如软件的设计、画面逼真程度,但作为一名程序员,实在对蓝图编程无感,对代码更加放心,还是更喜欢Unity的编程风格,因此选择了Unity,开始了漫长的Unity学习之路,学习资料是《Unity 5.X 3D游戏开发技术详解与典型案例》,欢迎交流。

一、Unity脚本概述

Unity脚本继承自MonBehaviour类,类中定义了各种回调方法,如Start、Update和FixedUpdate。

public class NewBehaviourScript: MonoBehaviour{...}

开发脚本时,主要时继承MonoBehaviour类并重写其中特定的方法。

Start方法:游戏场景加载时被调用,在该方法可以写一些游戏场景初始化的代码。

Update方法:在每一帧渲染之前被调用,大部分游戏代码在这里执行,除了物理部分的代码。

FixedUpdate方法:在固定的物理时间步调调用一次,基本物理行为代码执行的地方,如刚体Rigidbody,其中代码的执行和游戏的帧速率无关。

需要注意的是,1.在创建脚本时,类名字必须匹配文件名。2.类中的成员变量可以时private、protected和public,如果想在属性查看器中显示,其必须是public类型的。3.尽量避免在类中使用构造函数。

二、Unity脚本的基础语法

1.常用操作

Unity中很多对游戏对象的操作都是在脚本中修改对象的Transform(变换属性)与Rigidbody(刚体属性)参数来实现的。

让物体绕x轴旋转20°和让物体向前移动1个单位长度:

this.transform.Rotate(20,0,0); //绕x轴旋转20°
this.transform.Translate(0,0,1) //向前移动1个单位长度

第四个参数为Space枚举类型,Space.Self相对于自身轴(默认),Space.World相对于世界坐标系统。

2.记录时间

Time类中重要的变量为deltaTime,指的是从最近一次调用Update或FixedUpdate方法到现在的时间,如果想均匀地旋转一个物体,不考虑帧速率的情况下,可以乘以Time.deltaTime。

public GameObject gameObject; //声明一个游戏对象
void Update(){
    Vector3 te = gameObject.transform.position; //    获取游戏对象的位置坐标
    te.y += 5*Time.deltaTime; //沿y轴每秒上升5个单位
    gameObject.transform.position = te; //设置游戏对象的位置坐标
}

3.访问游戏对象组件(Component)

组件属于游戏对象,是游戏的属性,变量是在脚本中体现的,常用的组件可以通过简单的成员变量取得,所有的脚本都是组件。

常见的成员变量
组件名称 变量名称 组件名称 变量名称
Transform transform Rigidbody rigidbody
Renderer renderer Camera camera
Light light Animation animation
Collider collider    

在Unity 脚本中,附加到游戏对象上的组件可以通过GetComponent方法获得。

transform.Translate(1,0,0); //沿x轴移动一个单位,变量访问
GetComponent<Transform>().Translate(1,0,0) //沿x轴移动一个单位,组件访问

也可以通过GetComponent方法获取其他的脚本,比如有一个HelloWorld的脚本,里面有一个sayHello方法,HelloWorld脚本要与调用它的脚本附加在同一游戏对象上。

HelloWorld helloWorld = GetComponent<HelloWorld>(); //获取“HelloWorld”脚本组件
helloWorld.sayHello(); //执行sayhello方法

注意:C#中只有public类型的变量和方法才能在所有其他类中使用,private类型的变量和方法只能在自身类中使用,protected类型的变量和方法只能在子类和同命名空间下的类中使用。

4.访问其他游戏对象

(1)通过属性查看器指定参数。

(2)确定对象的层次关系,游戏对象在游戏组成对象列表中存在父子关系,在代码中可以通过获取Transform组件来找到子对象或父对象。

transform.Find("hand").Translate(0,0,1) //找到“hand”子对象
transform.parent.Translate(0,0,1) //找到父对象
transform.Find("hand").GetComponent<Test>().doSomething();
//找到子对象“hand”,同时执行“Test”脚本中的doSomething方法
transform.Find("hand").GetComponent<Rigidbody>()AddForce(0,0,2)//加一个沿z轴的大小为2的力

(3)通过名字或标签获取游戏对象

FindWithTag方法获取指定标签的游戏对象,Find方法获取指定名字的游戏对象。

GameObject name = GameObject.Find("somename"); //获取名称为“somename”的游戏对象
name.transform.Translate(0,0,1);
name.GetComponent<Test>().doSomething(); //执行Test脚本中的doSomething方法
GameObject tag = GameObject.FindWithTag("sometag"); //获取标签为“sometag”的游戏对象
tag.GetComponent<Test>().doSomething();

(4)通过传递参数获取游戏对象

一些事件回调方法的参数中包含了特殊的游戏对象或组件信息,例如触发碰撞事件的Collider组件。在OnTriggerStay方法的参数中有一个碰撞体参数,通过这个参数能得到碰撞的刚体。

void OnTriggerStay(Collider other){ //重写OnTriggerStay方法
    if(other.GetComponent<Rigidbody>()){ //如果该游戏对象上有刚体组件
        other.GetComponent<Rigidbody>().AddForce(0,0,2); //给刚体施加一个力
    }
}

(5)通过组件名称获取游戏对象

Unity脚本中可以通过FindObjectsOfType方法和FindObjectOfType方法来找到挂载特定类型组件的游戏对象。

Test test = FindObjectOfType<Test>(); //理解为Test代表挂载Test组件的游戏对象的类
Debug.Log(test.gameObject.name); //类比this.gameObject,this理解为当前脚本组件
Test[] tests = FindObjectsOfType<Test>();
foreach (Test re in tests){
    Debug.Log(te.gameObject.name);
}

注:关于GameObject与gameObject的理解,GameObject是一个类,是一个容器,可实例化为游戏对象,包含不同组件;gameObject获得当前脚本所挂载的对象,是一个实例化的结果,上例中test.gameObject可类比此意。gameObject是组件附加的游戏物体(不是组件,是MonoBehaviour类中可继承的成员变量),一个组件总是被附加到一个游戏物体。

5.向量

Vector2类表示二维向量,Vector3表示三维向量。向量初始化:

public Vector3 position1 = new Vector3();
public Vector3 position2 = new Vector3(1,1,2);
void Start(){
    position1.x = 1;
    position1.y = 1;
    position1.z = 2;
}

Vector3类中定义了很多常量,对应特殊的Vector3值。

Vector3类中常量对应的值
常量 常量
Vector3.zero Vector(0,0,0) Vector3.one Vector(1,1,1)
Vector3.forword Vector(0,0,1) Vector3.up Vector(0,1,0)
Vector3.right Vector(1,0,0)    

Vector3求两点之间的距离:

public Transform ren; 
//如果声明的是一个组件变量,需要在属性查看器中拖拽游戏对象到变量处并确定它的值
void Update(){
    if(Vector3.Distance(ren.position,transform.positon)<10){
        Debug.Log(ren.position);
    }
}

6.静态成员变量

在C#脚本中可以通过static关键字来创建全局变量,这样就可以在不同脚本间调用这个变量。

public static int test;

如果想从另外一个脚本中调用变量,可以通过“脚本名.变量名”的方法来调用。

Test.test = 1; //为Test脚本中的“test”变量赋值

未完待续

猜你喜欢

转载自blog.csdn.net/weixin_35747666/article/details/82915709
今日推荐