物体脚本的类都继承MonoBahaviour基类(只有继承类MonoBahaviour类才能挂载到GameObject上)
选中一个脚本点击Execution Order键:
会显示如下窗口:
点击下图的+按钮可以设置脚本执行顺序:
可以添加脚本(NewBehaviourScript是新添加的继承MonoBehaviour类的脚本)
游戏的本质就是一个死循环,每一次循环处理游戏逻辑就会更新—次画面,之所以能看到画面在动,是因为切换画面的速度到达一定时,人眼就认为画面是流畅的,—帧就是执行一次循环
游戏卡顿的原因:跑1帧游戏逻辑中的计算量过大,或者CPU不给力,不能在一帧的时间内处理完所有游戏逻辑
Unity 底层已经帮助我们做好了死循环
我们需要学习Unity的生命周期函数
利用它做好的规则来执行我们的游戏逻辑就行了
所有继承 MonoBehaviour 的脚本 最终都会挂载到GameObject游戏对象上
生命周期函数 就是该脚本对象依附的GameObject对象从出生到消亡整个生命周期中会通过反射自动调用的一些特殊函数
Unity帮助我们记录了一个GameObject对象依附了哪些脚本
会自动的得到这些对象,通过反射去执行一些固定名字的函数
注意:
生命周期函数的访问修饰符一般为 private和 protected
因为不需要在外部自己调用生命周期函数 都是 Unity 自己帮助我们调用的
当对象(自己这个类对象) 被创建时 才会调用该生命周期函数
private void Awake()
{
//在Unity中打印信息的两种方式
//1.没有继承MonoBehaviour类的时候
//Debug.Log("123");
//Debug.LogError("出错了");
//Debug.LogWarning("警告");
//2.继承了MonoBehaviour 有一个线程的方法 可以使用
print("Awake");
}
//对于我们来说 想要当一个对象被激活时 进行一些逻辑处理 就可以写在这个函数
private void OnEnable()
{
print("OnEable");
}
//主要作用还是用于初始化信息的 但是它相对于Awake来说 要晚一点
//因为它是在对象 进行第一次帧更新之前才会执行的
private void Start()
{
print("Strart");
}
//它主要是用于 进行物理更新
//它是每一帧的执行的 但是 这里的帧 和游戏帧 有点不同
//它的时间间隔 是可以在 protect setting中的 Time里去设置的
private void FixedUpdate()
{
print("FixedUpdate");
}
//主要用于处理游戏核心逻辑更新的函数
private void Update()
{
print("Update");
}
//一般这个更新是用来处理 摄像机位置更新相关内容的
//Update 和 LateUpdate 之间 Unity 进行了一些处理 处理我们动画相关的更新
private void LateUpdate()
{
print("LateUpdate");
}
//如果我们希望在一个对象失活时做一些处理 就可以在该函数中写逻辑
private void OnDisable()
{
print("OnDisable");
}
private void OnDestroy()
{
print("OnDestroy");
}
(这些生命周期函数 如果你不打算在其中写逻辑 那就不要写出这些生命周期函数 )
private int i1;
protected string str1;
加上强制序列化字段特性
[SerializeField]
所谓序列化就是把一个对象保存到一个文件或数据库字段中去
[SerializeField]
private int privateInt;
[SerializeField]
protected string protectedStr;
[HideInInspector]
public int publicInt = 10;
public bool publicBool = false;
在变量前加上特性 [HideInInspector]
[HideInInspector]
public int publicInt2 = 50;
public enum E_TestEnum
{
Normal,
Player,
Monster
}
[System.Serializable]
public struct MyStruct
{
public int age;
public bool sex;
}
[System.Serializable]
public class MyClass
{
public int age;
public bool sex;
}
public int[] array;
public List list;
public E_TestEnum type;
public GameObject gameObj;
//字典不能被Inspector窗口显示
public Dictionary dic;
//自定义类型变量
public MyStruct myStruct;
public MyClass myClass;
加上序列化特性 [System.Serializable]
字典怎样都不行
为成员分组
Header 特性 [Header("分组说明")]
[Header("基础属性")]
public int age;
public bool sex;
[Header("战斗属性")]
public int atk;
public int def;
为变量添加说明 [Tooltip("说明内容")]
[Tooltip("闪避")]
public int miss;
让两个字段间出现间隔 [Space()]
[Space()]
public int crit;
[Range(最大值,最小值)]
[Range(0,10)]
public float luck;
写参数就是对应行[Multiline(4)]
[Multiline()]
public string tips;
默认不写参数就是超过三行显示滚动条 [TextArea(3,4)]
最少显示3行,最多4行,超过四行就显示滚动条
[TextArea(3, 4)]
public string MyLife;
参数1 显示按钮名
参数2 方法名 不能有参数
[ContestMenuItem("显示按钮名","方法名")]
[ContextMenuItem("重置钱", "Test")]
public int money;
private void Test()
{
money = 0;
}
[ContextMenu("测试函数")]
[ContextMenu("哈哈哈")]
private void TestFun()
{
print("测试方法");
}
1.Inspector窗口中的变量关联的就是对象的成员变量,运行时改变他们就是在改成员变量
2.拖曳到GameObject对象后 再改变脚本中变量默认值 界面上不会改变
3.运行中修改的信息不会保存
print(this.gameObject.name);
得到对象位置信息
print(this.transform.position); //位置
print(this.transform.eulerAngles);//角度
print(this.transform.lossyScale); //缩放大小
//这种写法和上面都是一样的效果 都是得到依附的对象的位置信息
//this.gameObject.transform
this.enabled = true; //激活
this.enabled = false;//失活
//获取别的脚本对象 衣服的gameObject和transform位置信息
print(otherLesson3.gameObject.name);
print(otherLesson3.transform.position);
得到依附对象上挂载的其他脚本
//根据脚本名获取
lesson3_Test t=this.GetComponent("lesson3_Test") as lesson3_Test;
print(t);
//根据Type获取
t = this.GetComponent(typeof(lesson3_Test)) as lesson3_Test;
print(t);
//根据泛型获取 建议使用泛型获取 因为不用二次转换
t = this.GetComponent();
if (t != null)
{
print(t);
}
//只要你能够得到场景中别的对象或者对象依附的脚本
//那你就可以获取到它的所有信息
lesson3[] array = this.GetComponents();
print(array.Length);
List list = new List();
this.GetComponents(list);
print(list.Count);
//函数是有一个参数的 默认不传 是false
//意思就是 如果子对象失活 是不会去找这个对象上是否有某个脚本
//如果传 true 即使失活 也会找
t = this.GetComponentInChildren();
print(t);
//得子对象 挂载脚本 多个
lesson3_Test[] lts = this.GetComponentsInChildren(true);
print(lts.Length);
List list2 = new List();
this.GetComponentsInChildren(true, list2);
t = this.GetComponentInParent();
print(t);
lts = this.GetComponentsInParent();
print(lts.Length);
//它也有list的 和上面相同的套路
lesson3_Test l3t;
//提供了一个更加安全的 获取单个脚本的方法 如果得到了 会返回true
//然后再来进行逻辑处理即可
if (this.TryGetComponent(out l3t))
{
//逻辑处理
}