// 名字
print(this.gameObject.name);
this.gameObject.name = "Lesson4唐老狮改名";
print(this.gameObject.name);// 是否激活
print(this.gameObject.activeSelf);// 是否是静态
print(this.gameObject.isStatic);// 层级
print(this.gameObject.layer);// 标签
print(this.gameObject.tag);// transform
// this.transform 上一节课讲解的 通过Mono去得到的依附对象的GameObject的位置信息
// 他们得到的信息是一样 都是依附的GameObject的位置信息
print(this.gameObject.transform.position);
只要得到了一个 GameObject 对象,就可以得到它身上挂在的任何脚本信息通过 obj.GetComponent 来获得
两种找单个对象的共同点:
- 无法找到失活的对象的,只能找到激活的对象
- 如果场景中存在多个满足条件的对象,我们无法准确确定找到的是谁
// 1.查找单个对象
// 通过对象名查找
// 这个查找效率比较低下 因为他会在场景中的所有对象去查找
// 没有找到 就会返回null
GameObject obj2 = GameObject.Find("唐老狮");
if( obj2 != null ) print(obj2.name);
else print("没有找到对应对象");// 通过tag来查找对象
// GameObject obj3 = GameObject.FindWithTag("Player");
// 该方法和上面这个方法 效果一样 只是名字不一样而已
GameObject obj3 = GameObject.FindGameObjectWithTag("Player");
if (obj3 != null) print("根据tag找的对象" + obj3.name);
else print("根据tag没有找到对应对象");
// 得到某一个单个对象 目前有2种方式
// 1.是public从外部面板拖 进行关联
// 2.通过API去找
// 2查找多个对象
// 找多个对象的API 只能是通过tag去找多个 通过名字 是没有找多个的方法的// 通过tag找到多个对象
// 它也是 只能找到 激活对象 无法找到失活对象
GameObject[] objs = GameObject.FindGameObjectsWithTag("Player");
print("找到tag为Player对象的个数" + objs.Length);
// 还有几个查找对象相关是用的比较少的方法 是GameObject父类 Object提供的方法
// 引出额外知识点 Unity中的Object和C#中的万物之父的区别
// Unity里面的Object 不是指的万物之父object
// Unity里的Object 命名空间在UnityEngine中的 Object类 也是集成万物之父的一个自定义类
// C#中的Object 命名空间是在System中的
// 它可以找到场景中挂载的某一个脚本对象
// 效率更低 上面的GameObject.Find 和通过FindWithTag找 只是遍历对象
// 这个方法 不仅要遍历对象 还要遍历对象上挂载的脚本
Lesson4 o = GameObject.FindObjectOfType();
print(o.gameObject.name);
// 实例化对象(克隆对象)的方法
// 实例化(克隆)对象 它的作用 是根据一个GameObject对象 创建出一个和它一模一样的对象
GameObject obj5 = GameObject.Instantiate(myObj);
// 以后学了更多知识点 就可以在这操作obj5
// 如果你继承了 MonoBehavior 其实可以不用写GameObject一样可以使用
// 因为 这个方法时Unity里面的 Object基类提供给我们的 所以可以直接用
// Instantiate(myObj);
// 删除对象的方法
GameObject.Destroy(myObj2);
// 第二个参数 代表延迟几秒钟删除
GameObject.Destroy(obj5, 5);
// Destroy不仅可以删除对象 还可以删除脚本
// GameObject.Destroy(this);
// 删除对象有两种作用
// 1.是删除指定的一个游戏对象
// 2.是删除一个指定的脚本对象
// 注意:这个Destroy方法 不会马上移除对象 只是给这个对象加了一个移除标识
// 一般情况下 它会在下一帧时把这个对象移除并从内存中移除
// 如果没有特殊需求 就是一定要马上移除一个对象的话
// 建议使用上面的 Destroy方法 因为 是异步的 降低卡顿的几率
// 下面这个方法 就是立即把对象 从内存中移除了
// GameObject.DestroyImmediate(myObj);
// 如果是继承MonoBehavior的类 不用写GameObject
// Destroy(myObj2);
// DestroyImmediate(myObj);
// 过场景不移除
// 默认情况 在切换场景时 场景中对象都会被自动删除掉
// 如果你希望某个对象 过场景不被移除
// 下面这句代码 就是不想谁过场景被移除 就传谁
// 一般都是传 依附的GameObject对象
// 比如下面这句代码的意思 就是自己依附的GameObject对象 过场景不被删除
GameObject.DontDestroyOnLoad(this.gameObject);
// 如果继承MOnoBehavior也可以直接写
// DontDestroyOnLoad(this.gameObject);
// 创建空物体
// new一个GameObject就是在创建一个空物体
GameObject obj6 = new GameObject();
GameObject obj7 = new GameObject("创建的空物体");
GameObject obj8 = new GameObject("顺便加脚本的空物体", typeof(Lesson2), typeof(Lesson1));
// 为对象添加脚本
// 继承MOnoBehavior的脚本 是不能够去new
// 如果想要动态的添加继承MonoBehavior的脚本 在某一个对象上
// 直接使用GameObject提供的方法即可
Lesson1 les1 = obj6.AddComponent(typeof(Lesson1)) as Lesson1;
// 用泛型更方便
Lesson2 les2 = obj6.AddComponent();
// 通过返回值 可以得到加入的脚本信息
// 来进行一些处理// 得到脚本的成员方 和继承Mono的类得到脚本的方法 一模一样
// 标签比较
// 下面两种比较的方法 是一样的
if(this.gameObject.CompareTag("Player")) print("对象的标签 是 Player");
if(this.gameObject.tag == "Player") print("对象的标签 是 Player");
// 设置激活失活
// false 失活
// true 激活
obj6.SetActive(false);
obj7.SetActive(false);
obj8.SetActive(false);
次要的成员方法了解即可,不建议使用
下面讲的方法,都不建议大家使用,效率比较低
通过广播或者发送消息的形式,让自己或者别人执行某些行为方法
// 通知自己 执行什么行为
// 命令自己 去执行这个TestFun这个函数 会在自己身上挂在的所有脚本去找这个名字的函数
// 它会去找到 自己身上所有的脚本 有这个名字的函数去执行
this.gameObject.SendMessage("TestFun");
this.gameObject.SendMessage("TestFun2", 199);
// 广播行为 让自己和自己的子对象执行
// this.gameObject.BroadcastMessage("函数名");
// 向父对象和自己发送消息 并执行
// this.gameObject.SendMessageUpwards("函数名");
// 时间停止 Time.timeScale = 0;
// 回复正常 Time.timeScale = 1;
// 2倍速 Time.timeScale = 2;
// 帧间隔时间 主要是用来计算位移
// 路程 = 时间*速度
// 根据需求 选择参与计算的间隔时间
// 如果希望 游戏暂停时就不动的 那就使用deltaTime
// 如果希望 不受暂停影响 unscaledDeltaTime
// 帧间隔时间:最近的一帧 用了多长时间(秒)
// 受scale影响
print("帧间隔时间" + Time.deltaTime);
// 不受scale影响的帧间隔时间
print("不受scale影响的帧间隔时间" + Time.unscaledDeltaTime);
// 它主要用来计时 单机游戏中计时
// 受scale影响
print("游戏开始到现在的时间:" + Time.time);
// 不受scale影响
print("不受scale影响的游戏开始到现在的时间:" + Time.unscaledTime);
private void FixedUpdate()
{
// 受scale影响
print(Time.fixedDeltaTime);
// 不受scale影响
print(Time.fixedUnscaledDeltaTime);
}
// 从开始到现在游戏跑了多少帧(次循环) print(Time.frameCount);
Time 相关的内容
最常用的就是
帧间隔时间,就用计算位移相关内容
时间缩放比例,用来暂停或者倍速等等
帧数(帧同步)
// 常用
print(Vector3.zero); // 0 0 0
print(Vector3.right); // 1 0 0
print(Vector3.left); // -1 0 0
print(Vector3.forward); // 0 0 1
print(Vector3.back); // 0 0 -1
print(Vector3.up); // 0 1 0
print(Vector3.down); // 0 -1 0
// 常用的一个方法
// 计算两个点之间的距离的方法
print(Vector3.Distance(v1, v2));
// 相对世界坐标系
// this.gameObject.transform
// 通过position得到的位置 是相对于 世界坐标系的 原点的位置
// 可能和面板上显示的 是不一样的
// 因为如果对象有父子关系 并且父对象位置 不在原点 那么 和面板上肯定就是不一样的
print(this.transform.position);
// 相对父对象
// 这两个坐标 对于我们来说 很重要 如果你想以面板坐标为准来进行位置设置
// 那一定是通过localPosition来进行设置的
print(this.transform.localPosition);
// 他们两个 可能出现是一样的情况
// 1.父对象的坐标 就是世界坐标系原点0,0,0
// 2.对象没有父对象
// 注意:位置的赋值不能直接改变x,y,z 只能整体改变
// 不能单独改 x y z某一个值
// this.transform.position.x = 10;
this.transform.position = new Vector3(10, 10, 10);
this.transform.localPosition = Vector3.up * 10;
// 如果只想改一个值x y和z要保持原有坐标一致
// 1.直接赋值
this.transform.position = new Vector3(19, this.transform.position.y, this.transform.position.z);
// 2.先取出来 再赋值
// 虽然不能直接改 transform的 xyz 但是 Vector3是可以直接改 xyz的
// 所以可以先取出来改Vector3 再重新赋值
Vector3 vPos = this.transform.localPosition;
vPos.x = 10;
this.transform.localPosition = vPos;
// 如果你想得到对象当前的 一个朝向
// 那么就是通过 trnasform. 出来的
// 对象当前的各朝向
// 对象当前的面朝向
print(this.transform.forward);
// 对象当前的头顶朝向
print(this.transform.up);
// 对象当前的右手边
print(this.transform.right);
// 理解坐标系下的位移计算公式
// 路程 = 方向 * 速度 * 时间// 方式一 自己计算
// 想要变化的 就是 position// 用当前的位置 + 我要动多长距离 得出最终所在的位置
// this.transform.position = this.transform.position + this.transform.up * 1 * Time.deltaTime;// 因为我用的是 this.transform.forward 所以它始终会朝向相对于自己的面朝向去动
// this.transform.position += this.transform.forward * 1 * Time.deltaTime;// 方向非常重要 因为 它决定了你的前进方向
// this.transform.position += Vector3.forward * 1 * Time.deltaTime;// 方式二 API
// 参数一:表示位移多少 路程 = 方向 * 速度 * 时间
// 参数二:表示 相对坐标系 默认 该参数 是相对于自己坐标系的// 1.相对于世界坐标系的 Z轴 动 始终是朝 世界坐标系 的 Z轴正方向移动
this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.World);// 2.相对于世界坐标的 自己的面朝向去动 始终朝自己的面朝向移动
this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.World);// 3.相对于自己的坐标系 下的 自己的面朝向向量移动 (一定不会这样让物体移动) XXXXXXX
// this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.Self);// 4.相对于自己的坐标系 下的 Z轴正方向移动 始终朝自己的面朝向移动
this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.Self);// 注意:一般使用API来进行位移
// 相对世界坐标角度
print(this.transform.eulerAngles);// 相对父对象角度
print(this.transform.localEulerAngles);// 注意:设置角度和设置位置一样 不能单独设置xyz 要一起设置
// 如果我们希望改变的 角度 是面板上显示的内容 那一点是改变 相对父对象的角度
// this.transform.localEulerAngles = new Vector3(10, 10, 10);
// this.transform.eulerAngles = new Vector3(10, 10, 10);
print(this.transform.localEulerAngles);
// 自己计算(省略不讲了 和位置一样 不停改变角度即可)
// API计算
// 自转
// 每个轴 具体转多少度
// 第一个参数 相当于 是旋转的角度 每一帧
// 第二个参数 默认不填 就是相对于自己坐标系 进行的旋转
// this.transform.Rotate(new Vector3(0, 10, 0) * Time.deltaTime);
this.transform.Rotate(new Vector3(0, 10, 0) * Time.deltaTime, Space.World);// 相对于某个轴 转多少度
// 参数一:是相对哪个轴进行转动
// 参数二:是转动的 角度 是多少
// 参数三:默认不填 就是相对于自己的坐标系 进行旋转
// 如果填 可以填写相对于 世界坐标系进行旋转
// this.transform.Rotate(Vector3.right, 10 * Time.deltaTime);
this.transform.Rotate(Vector3.right, 10 * Time.deltaTime, Space.World);// 相对于某一个点转
// 参数一:相当于哪一个点 转圈圈
// 参数二:相对于那一个点的 哪一个轴转圈圈
// 参数三:转的度数 旋转速度 * 时间
this.transform.RotateAround(Vector3.zero, Vector3.right, 10 * Time.deltaTime);
// 相对世界坐标系
print(this.transform.lossyScale);
// 相对本地坐标系(父对象)
print(this.transform.localScale);// 注意:
// 1.同样缩放不能只改xyz 只能一起改(相对于世界坐标系的缩放大小只能得 不能改)
// 所以 我们一般要修改缩放大小 都是改的 相对于父对象的 缩放大小 localScale
this.transform.localScale = new Vector3(3, 3, 3);// 2.Unity没有提供关于缩放的API
// 之前的 旋转 位移 都提供了 对应的 API 但是 缩放并没有
// 如果你想要 让 缩放 发生变化 只能自己去写(自己算)
this.transform.localScale += Vector3.one * Time.deltaTime;// 让一个对象的面朝向 可以一直看向某一个点或者某一个对象
// 看向一个点 相对于世界坐标系的
this.transform.LookAt(Vector3.zero);
// 看向一个对象 就传入一个对象的 Transform信息
this.transform.LookAt(lookAtObj);
// 获取父对象
print(this.transform.parent.name);
// 设置父对象 断绝父子关系
this.transform.parent = null;
// 设置父对象 认爸爸
this.transform.parent = GameObject.Find("Father2").transform;// 通过API来进行父子关系的设置
this.transform.SetParent(null); // 断绝父子关系
this.transform.SetParent(GameObject.Find("Father2").transform); // 认爸爸// 参数一:我的父亲
// 参数二:是否保留世界坐标的 位置 角度 缩放 信息
// true 会保留 世界坐标下的状态 和 父对象 进行计算 得到本地坐标系的信息
// false 不会保留 会直接把世界坐标系下的 位置角度缩放 直接赋值到 本地坐标系下
this.transform.SetParent(GameObject.Find("Father3").transform, false);
// 就是和自己的所有儿子 断绝关系 没有父子关系了
this.transform.DetachChildren();
// 按名字查找儿子
// 找到儿子的 transform信息
// Find方法 是能够找到 失活的对象的 !!!!! GameObject相关的 查找 是不能找到失活对象的
print(this.transform.Find("Cube (1)").name);
// 他只能找到自己的儿子 找不到自己的孙子 !!!!!!
print(this.transform.Find("GameObject").name);
// 虽然它的效率 比GameObject.Find相关 要高一些 但是 前提是你必须知道父亲是谁 才能找// 遍历儿子
// 如何得到有多少个儿子
// 1.失活的儿子也会算数量
// 2.找不到孙子 所以孙子不会算数量
print(this.transform.childCount);// 通过索引号 去得到自己对应的儿子
// 如果编号 超出了儿子数量的范围 那会直接报错的
// 返回值 是 transform 可以得到对应儿子的 位置相关信息
this.transform.GetChild(0);for (int i = 0; i < this.transform.childCount; i++)
print("儿子的名字:" + this.transform.GetChild(i).name);
// 判断自己的爸爸是谁
// 一个对象 判断自己是不是另一个对象的儿子
if(son.IsChildOf(this.transform)) print("是我的儿子");// 得到自己作为儿子的编号
print(son.GetSiblingIndex());
// 把自己设置为第一个儿子
son.SetAsFirstSibling();
// 把自己设置为最后一个儿子
son.SetAsLastSibling();
// 把自己设置为指定个儿子
// 就算你填的数量 超出了范围(负数或者更大的数) 不会报错 会直接设置成最后一个编号
son.SetSiblingIndex(1);
// 世界坐标系转本地坐标系 可以帮助我们大概判断一个相对位置// 世界坐标系的点 转换 为相对本地坐标系的点
// 受到缩放影响
print("转换后的点 " + this.transform.InverseTransformPoint(Vector3.forward));// 世界坐标系的方向 转换 为相对本地坐标系的方向
// 不受缩放影响
print("转换后的方向" + this.transform.InverseTransformDirection(Vector3.forward));// 受缩放影响
print("转换后的方向(受缩放影响)" + this.transform.InverseTransformVector(Vector3.forward));
// 本地坐标系的点 转换 为相对世界坐标系的点 受到缩放影响
print("本地转世界点" + this.transform.TransformPoint(Vector3.forward));// 本地坐标系的方向 转换 为相对世界坐标系的方向
// 不受缩放影响
print("本地转世界方向" + this.transform.TransformDirection(Vector3.forward));// 受缩放影响
print("本地转世界方向(受缩放影响)" + this.transform.TransformVector(Vector3.forward));
// 屏幕坐标的原点 是在 屏幕的左下角 往右是X轴正方向 往上时Y轴正方向
// 返回值时Vector3 但是只有 x和y有值 z一直是0 是因为屏幕本来就是2D的 不存在Z轴
print(Input.mousePosition);
// 鼠标按下相关检测 对于我们来说
// 比如: 1.可以做 发射子弹
// 2.可以控制摄像机 转动// 鼠标按下一瞬间 进入
// 0左键 1右键 2中键
// 只要按下的这一瞬间 进入一次
if(Input.GetMouseButtonDown(0)) print("鼠标左键按下了");// 鼠标抬起一瞬间 进入
if(Input.GetMouseButtonUp(0)) print("鼠标左键抬起了");// 鼠标长按按下抬起都会进入
// 就是 当按住按键不放时 会一直进入 这个判断
if(Input.GetMouseButton(1)) print("右键按下");// 中键滚动
// 返回值的 y -1往下滚 0没有滚 1往上滚
// 它的返回值 是Vector的值 我们鼠标中键滚动 会改变其中的Y值
print(Input.mouseScrollDelta);
// 比如说 按一个键释放一个技能或者切换武器 等等的操作
// 键盘按下
if(Input.GetKeyDown(KeyCode.W)) print("W键按下");// 传入字符串的重载
// 这里传入的 字符串 不能是大写的 不然会报错
// 只能传入小写字符串
if(Input.GetKeyDown("q")) print("q按下");// 键盘抬起
if(Input.GetKeyUp(KeyCode.W)) print("W键抬起");// 键盘长按
if(Input.GetKey(KeyCode.W)) print("W键长按");
在 Edit --> Project Setting --> Input Manager 中设置默认轴
// 我们学习鼠标 键盘输入 主要是用来
// 控制玩家 比如 旋转 位移等等
// 所以Unity提供了 更方便的方法 来帮助我们控制 对象的 位移和旋转// 键盘AD按下时 返回 -1到1之间的变换
// 相当于 得到得这个值 就是我们的 左右方向 我们可以通过它来控制 对象左右移动 或者左右旋转
float h = Input.GetAxis("Horizontal");// 键盘SW按下时 返回 -1到1之间的变换
// 得到得这个值 就是我们的 上下方向 我们可以通过它来控制 对象上下移动 或者上下旋转
print(Input.GetAxis("Vertical"));// 鼠标横向移动时 -1 到 1 左 右
print(Input.GetAxis("Mouse X"));// 鼠标竖向移动时 -1 到 1 下 上
print(Input.GetAxis("Mouse Y"));// 我们默认的 GetAxis方法 是有渐变的 会总 -1~0~1之间 渐变 会出现小数
// GetAxisRaw方法 和 GetAxis使用方式相同
// 只不过 它的返回值 只会是 -1 0 1 不会有中间值
// 是否有任意键或鼠标长按
if(Input.anyKey) print("有一个键长按");// 是否有任意键或鼠标按下
if(Input.anyKeyDown)
{
print("有一个键 按下");
// 这一帧的键盘输入
print(Input.inputString);
}// 手柄输入相关
// 得到连接的手柄的所有按钮名字
string[] strs = Input.GetJoystickNames();// 某一个手柄键按下
if(Input.GetButtonDown("Jump")) { }// 某一个手柄键抬起
if (Input.GetButtonUp("Jump")) { }// 某一个手柄键长按
if (Input.GetButton("Jump")) { }// 移动设备触摸相关
if(Input.touchCount > 0)
{
Touch t1 = Input.touches[0];
// 位置
print(t1.position);
// 相对上次位置的变化
print(t1.deltaPosition);
}// 是否启用多点触控
Input.multiTouchEnabled = false;// 陀螺仪(重力感应)
// 是否开启陀螺仪 必须开启 才能正常使用
Input.gyro.enabled = true;
// 重力加速度向量
print(Input.gyro.gravity);
// 旋转速度
print(Input.gyro.rotationRate);
// 陀螺仪 当前的旋转四元数
// 比如 用这个角度信息 来控制 场景上的一个3D物体受到重力影响
// 手机怎么动 它怎么动
print(Input.gyro.attitude);
// Input.GetAxis("Horizontal"); 水平方向 -1到1之间的值 0就是没有按下
// Input.GetAxis("Vertical"); 竖直方向 -1到1之间的值 0就是没有按下
// ws键 控制位移
// 公式: 前进方向 * 速度 * 时间 * 当前是否移动(-1~1 相当于 正向还是反向的感觉 不按就不动 0)
this.transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime * Input.GetAxis("Vertical"));// ad键 控制 左右转向
// 公式: 转动的轴 * 速度 * 时间 * 当前是否移动(-1~1 相当于 正向还是反向的感觉 不按就不动 0)
this.transform.Rotate(Vector3.up * rotateSpeed * Time.deltaTime * Input.GetAxis("Horizontal"));
// 鼠标输入相关
// Input.GetAxis("Mouse X");
// 公式: 转动的轴 * 速度 * 时间 * 当前是否移动(-1~1 相当于 正向还是反向的感觉 不按就不动 0)
head.Rotate(Vector3.up * headRotateSpeed * Time.deltaTime * Input.GetAxis("Mouse X"));
// Input.mouseScrollDelta.y
pkPos.Rotate(Vector3.right * pkRotateSpeed * Time.deltaTime * Input.mouseScrollDelta.y);
// 当前屏幕分辨率
Resolution r = Screen.currentResolution;
print("当前屏幕分辨率的宽" + r.width + "高" + r.height);// 屏幕窗口当前宽高
// 这得到的 是当前 窗口的 宽高 不是设备分辨率的宽高
// 一般写代码 要用窗口宽高 做计算时 就用他们
print(Screen.width);
print(Screen.height);// 屏幕休眠模式
Screen.sleepTimeout = SleepTimeout.NeverSleep;
// 运行时是否全屏模式
Screen.fullScreen = true;// 窗口模式
// 独占全屏 FullScreenMode.ExclusiveFullScreen
// 全屏窗口 FullScreenMode.FullScreenWindow
// 最大化窗口 FullScreenMode.MaximizedWindow
// 窗口模式 FullScreenMode.Windowed
Screen.fullScreenMode = FullScreenMode.Windowed;// 移动设备屏幕转向相关
// 允许自动旋转为左横向 Home键在左
Screen.autorotateToLandscapeLeft = true;// 允许自动旋转为右横向 Home键在右
Screen.autorotateToLandscapeRight = true;// 允许自动旋转到纵向 Home键在下
Screen.autorotateToPortrait = true;// 允许自动旋转到纵向倒着看 Home键在上
Screen.autorotateToPortraitUpsideDown = true;// 指定屏幕显示方向
Screen.orientation = ScreenOrientation.Landscape;
// 设置分辨率 一般移动设备不使用
Screen.SetResolution(1920, 1080, false);
sleepTimeout = SleepTimeout.NeverSleep;