一、脚本相关概念
1-脚本的定义
- 脚本可以附加在游戏物体上,用于定义游戏对象行为的指令代码,如:xxx.cs文件
- Unity支持三种高级编程语言:C#、javascript和Boo Script(Unity4以前支持)
2-语法结构
using 命名空间;
public class 类名: MonoBehaviour
{
void 方法名();
Debug.Log("调试显示信息");
print("本质就是Debug.Log方法");
}
- 文件名与类名必须一致
- 写好的脚本必须附加到物体上才执行
- 附加到游戏物体的脚本类必须从MonoBehaviour类继承
3-脚本编译过程
- 编译运行过程:
- 源代码:(CLS)—>中间语言(dll文件)–(Mono Runtime)- >机器码
4-创建脚本文件
鼠标右键创建即可,选择C# script
在unity中创建出的C#脚本文件模板内部的构造:
using UnityEngine;
using System.Collections;
public class demo01 : MonoBehaviour {
void Start () {
}
void Update () {
}
}
模板也是可以自定义的,我们到unity的目录下:
修改为:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class #SCRIPTNAME# : MonoBehaviour
{
}
5-脚本在Unity中的一些操作
- 拖动脚本文件到游戏对象上,可以发现创建了一个对象,通过这个脚本对象我们可以进行许多操作
- 然后我们修改一下脚本内容:
public class NewBehaviourScript : MonoBehaviour
{
public int A;
private string B = "abc";
[SerializeField]
private bool C = true;
[Range(1, 100)]
public int D = 10;
[HideInInspector]
public float E = 1.0f;
}
- 查看我们之前的游戏对象的Inspector窗口中的脚本位置,发现出现相关的变量,而且可以进行设置
6-脚本生命周期(重要)
6-1.定义
- Unity脚本从唤醒到销毁的过程
- 消息:当满足某种条件Unity引擎自动调用的函数
- 脚本生命周期也被称为必然事件
6-2.初始阶段
- Awake()唤醒:当物体载入时立即调用1次;常用于在游戏开始前进行初始化。可以判断当满足某种条件执行此脚本,然后使用此语句this.enable=true,表示会被调用。this.enable=false,之后的方法就不会被执行了。
- OnEnable()当可用:每当脚本对象启用时调用。
- Start()开始:物体载入且脚本对象启用时被调用1次。常用于数据或游戏逻辑初始化,执行时机晚于Awake。
public class LIfeCycle : MonoBehaviour
{
private void Awake()
{
Debug.Log("Awake()方法被调用了!");
}
private void OnEnable()
{
Debug.Log("OnEnable()方法被调用了!");
}
private void Start()
{
Debug.Log("Start()方法被调用了!");
}
}
将脚本挂到游戏对象上,测试一下
6-3.物理阶段
- FixedUpdate()表示固定更新:脚本启用后,固定时间被调用,适用于对游戏对象做物理操作,例如移动等。固定是0.02秒更新一次,这个数值我们可以进行更改,设置更新频率"Edit" --> “Project Setting”–>“Time” --> “Fixed Timestep” 值,默认为0.02s。
- OnCollisionXXX()碰撞:当满足碰撞条件时调用。
- OnTriggerXXX()触发:当满足触发条件时调用。
6-4.输入事件
需要碰撞器Collider,即unity中的这些collider:
- OnMouseEnter()鼠标移入:鼠标移入到当前Collider时调用。
- OnMouseOver()鼠标经过:鼠标经过当前Collider时调用。
- OnMouseExit()鼠标离开:鼠标离开当前Collider时调用。
- OnMouseDown()鼠标按下:鼠标按下当前Collider时调用。
- OnMouseUp()鼠标抬起:鼠标在当前Collider上抬起时调用。
6-5.游戏逻辑
- Update()更新:脚本启用后,每次渲染场景时调用,频率与设备性能及渲染量有关
- LateUpdate()延迟更新:在Update函数被调用后执行,适用于跟随逻辑
6-6.场景渲染
- OnBecameVisible()当可见:当Mesh Renderer在任何相机上可见时调用
- OnBecameInvisible()当不可见:当Mesh Renderer在任何相机上都不可见时调用
6-7.结束阶段
- OnDisable()当不可用:对象变为不可用或附属游戏对象非激活状态时此函数被调
- OnDestroy()当销毁:当脚本销毁或附属的游戏对象被销毁时被调用
- OnApplicationQuit()当程序结束:应用程序退出时被调用
6-8.示例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LIfeCycle : MonoBehaviour
{
private void Awake()
{
Debug.Log("Awake()方法被调用了!");
}
private void OnEnable()
{
Debug.Log("OnEnable()方法被调用了!");
}
private void Start()
{
Debug.Log("Start()方法被调用了!");
}
private void FixedUpdate()
{
Debug.Log("FixedUpdate()方法被调用了!");
}
private void Update()
{
Debug.Log("Update()方法被调用了!");
}
}
6-9.脚本生命周期图:
具体就是脚本的一些函数执行流程:
二、开发工具
1-MonoDevelop
MonoDevelop:Unity:Unity自带脚本编辑器,创建Mono应用程序,适用于Linux、Mac OS X和Windows的集成开发环境,支援C#、BOO和JavaScript等高级编程语言。
2-Visual Studio(推荐)
微软公司的开发工具包,包括了整个软件生命周期中需要的大部分工具,如团队开发工具、集成开发环境等等。
3-修改默认开发工具
- 在Unity中通过菜单设置修改默认的脚本编辑器:Edit一Preferences一External Tools一External Script Editor
- 如安装了visual studio选择即可,以后在unity打开脚本自动启动vs打开
三、常用API
1-Unity核心类图
注意看图中的MonoBehaviour,一般我们是继承MonoBehaviour来编写脚本
2-脚本的Component类
主要是获取游戏对象的组件,改变组件相关数值
2-1.操作unity编译器中的属性
主要是使用GetComponent()方法获取组件,然后在对组件的属性进行操作
- 创建一个脚本,并将脚本拖动到游戏对象上
- 编辑脚本内容如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ComponentDemo : MonoBehaviour
{
private void OnGUI()
{
if (GUILayout.Button("修改位置"))
{
this.transform.position = new Vector3(0, 0, 10);
}
if (GUILayout.Button("修改BoxCollider大小"))
{
this.GetComponent<BoxCollider>().size = new Vector3(1, 2, 3);
}
if (GUILayout.Button("GetComponents"))
{
var allComponents = this.GetComponents<Component>();
foreach(var item in allComponents)
{
print("获取到的组件为:" + item.GetType());
}
}
}
}
- 点击修改位置按钮后,物体的transform的position属性变为代码中设置值
- 运行后查看,发现我们其实可以获取Inspector面板的组件信息,并加以修改
2-2.获取游戏对象后代和先辈的组件
- 将脚本拖拽到游戏对象上,然后创建后代cube(后代cube无脚本)
- 在脚本中添加:
if (GUILayout.Button("GetComponentsInChildren"))
{
var allComponents = this.GetComponentsInChildren<MeshRenderer>();
foreach (var item in allComponents)
{
print("获取到后代的组件为:" + item.GetType());
}
}
if (GUILayout.Button("GetComponentsInParent"))
{
var allComponents = this.GetComponentsInParent<MeshRenderer>();
foreach (var item in allComponents)
{
print("获取到后代的组件为:" + item.GetType());
}
}
- 运行点击对应按钮,可以发现获取到了相应组件
3-脚本的Transform类
主要是设置游戏对象物体的旋转缩放位置等等,可以制作游戏移动之类的操作
3-1.获取子对象变换组件
- 还是只在cube上设置脚本
- 将下列内容写入脚本
if (GUILayout.Button("foreach-transform"))
{
foreach (Transform child in this.transform)
{
print("获取到子物体的变换组件为:" + child.name);
}
}
- 查看结果,只打印出子类的名字,子类的子类(孙子类)则不会打印。
3-2.改变对象的坐标-1
- 还是脚本作用在cube上
- 添加脚本内容如下:
if (GUILayout.Button("z轴移动1m"))
{
this.transform.Translate(0, 0, 1);
}
if (GUILayout.Button("y轴旋转1m"))
{
this.transform.Rotate(0, 10, 0);
this.transform.Rotate(0, 10, 0, Space.World);
}
- 点击之后可以发现物体移动
3-3.改变对象的坐标-2
- 还是将脚本作用与cube,内容如下:
public class ComponentDemo : MonoBehaviour
{
public Transform tf;
private void OnGUI()
{
if (GUILayout.Button("GetParent-Transform"))
{
Transform parentTF =this.transform.parent;
}
if (GUILayout.Button("SetParent-true"))
{
this.transform.SetParent(tf, true);
}
if (GUILayout.Button("SetParent-false"))
{
this.transform.SetParent(tf, false);
}
}
}
- 查看新增一个Tf变量,这里Tf可以接收一个Transform
- 我们新建一个cube(6)传入它的Transform给cube,类似于(public Transform tf=“cube的Transform组件”)
- 运行,然后点击
SetParent-true 按钮,然后改变cube(6)的位置,发现cube和cube(6)做相对运动(其实这就是正常的子物体与父物体关系)。类比载具,相当于cube上了名为cube(6)的车。cube就跟着父物体cube(6)一起走了。 - 运行,然后点击
SetParent-false 按钮,会发现cube的坐标会直接变为cube(6)的坐标(即重叠了),然后拖动cube(6),发现cube不会再移动。查看cube的坐标为(0,0,0),查看cube(6)的坐标为(0,2,0),所以就是cube将cube(6)的位置作为了参照物而已
- 总结:
SetParent-true 就是正常的父物体与子物体的关系,子物体跟着父物体移动,无需记忆;SetParent-false 则是将子物体的Transform的参照点改变了,原本物体创建都是默认将世界坐标作为参照点,这里是直接将父物体的坐标设置为了参照点而已。
3-4.查找子物体的Transform
if (GUILayout.Button("FindChildTransform"))
{
Transform childTF=this.transform.Find("cube(1)");
}
4-GameObject类
4-1.激活状态
- 激活状态对应到Inspector面板中的勾选框
- 相关脚本如下:
public class GameObjectDemo : MonoBehaviour
{
private void OnGUI()
{
}
}
4-2.创建GameObject
- 脚本内容如下:
public class GameObjectDemo : MonoBehaviour
{
private void OnGUI()
{
if (GUILayout.Button("添加光源组件"))
{
GameObject lightGo = new GameObject();
Light light=lightGo.AddComponent<Light>();
light.color=Color.red;
light.type = LightType.Point;
}
}
}
- 将脚本拖拽到cube运行,点击按钮后,Hierarchy面板创建了一个GameObject正好是我们定义的光组件
下:
public class GameObjectDemo : MonoBehaviour
{
private void OnGUI()
{
if (GUILayout.Button("添加光源组件"))
{
GameObject lightGo = new GameObject();
Light light=lightGo.AddComponent<Light>();
light.color=Color.red;
light.type = LightType.Point;
}
}
}
- 将脚本拖拽到cube运行,点击按钮后,Hierarchy面板创建了一个GameObject正好是我们定义的光组件
|