• 官方文档 unity.cn/中文文档
  • 本地路径 Editor/Data/Documentation/en/Manual/index.html
  • 设置脚本默认打开方式:  Edit/Preferences/External Tools/ Exteral Script Editor
    image.png

    Helloworld

  • 添加一个脚本

    • 右键 Create/C# Script
    • 文件名必须规范, 文件名即类名 如SimpleLogic
  • 双击在vs中打开脚本,检查类名与文件名是否一致
  • 在vs中编辑代码

    • 添加一行打印输出
    void Start(){
      Debug.Log("Hello World")
    }
    • 其中Debug是Unity API中的一个工具类
  • Ctrl+S 保存代码,关闭vs
  • 编译

    • 保存会自动编译
  • 挂载脚本

    • 点Add Component,选Scripts/Simple Logic
    • 或者,直接将脚本拖到Inspector窗口的最下方
  • 运行游戏

    • 点play按钮,运行

  • Frame 一个游戏帧
  • FrameRate 帧率|刷新率
  • FPS Frames Per Second 每秒更新多少帧
    Update() 帧更
  • 新此方法会被游戏引擎定时调用,以更新游戏的状态

    帧更新

  • Time.time 游戏时间
  • Time.deltaTime 距离上次更新的时间差
  • 显然,帧率是不固定的,Unity会尽量较快地更新

Unity不支持固定的帧率,但可以设定一个近似帧率

  • Application.targetFameRate=60
    其中,指示Unity尽量以FPS=60的帧率更新游戏

    物体

    基本属性

  • this 当前脚本组件
  • this.gameObject 当前物体
  • this.gameObjecet.name 当前物体的名字
  • this.gameObject.transform 当前物体下的transform组件
  • 为了简化书写 也可写作this.transform 效果相同

    GameObject obj = this.gameObject;
    string name = obj.name;
    Transform tr = obj.transform;

    API中的大部分类型,来自于UnityEngine
    using UnityEngine;

  • 基类 MonoBehaviour
  • 游戏物体 GameObject
  • 变换组件 Transform
  • 三维向量 Vector3

    坐标

    物体的坐标

  • transform.position 世界坐标
  • transform.localPosition 本地坐标
    一般用localPosition 与Inspector窗口中的一致

    Vector3 pos = tr.position;
    Vector3 pos1 = tr.localPosition;
    tr.localPosition = new Vector3(1.2f, 1.2f, 1.2f);

    移动

    float speed = 3;
    float distance=speed * Time.deltaTime;
    
    Vector3 pos=this.transform.localPosotion;
    pos.x+=distance;
    this.transform.localPosotion=pos;

    相对运动

    一般使用trasform.Translate(dx,dy,dz,space)实现相对运动

其中dx,dy,dz是坐标增量

  • 例如transform.Translate(0,0,distance)Z方向增加distance
float speed = 3;
float distance=speed * Time.deltaTime;
this.transform.Translate(0,0,distance);

其space:

  • Space.World 相对于世界坐标系
  • Space.Self 相对于自身坐标系(本地坐标系)

运动方向

  • 获取目标物体(根据名字|路径来查找物体)

    • GameObject flag=GameObject.Find("红旗")
  • 转向目标(使物体的z轴指向物体)

    • this.trnsform.LookAt(flag.transform);
  • 向前运动,forward,+z方向(沿物体自身坐标系的轴向运动)

    • this.transform.Translate(0,0,dz,Space.Self)
  • 若目标在空中,则物体也向空中运动
  • 向量测距

  • p1=火车.transform.position  
  • p2=红旗.transform.position  
  • p=p1-p2  
  • distance=p.magnitude

play时观察跟随

image.png

旋转

给物体转一个旋转角度

  • Quanternion 四元组(x,y,z,w)

    • transform.rotaion=... 不便操作,官方不建议使用
  • 欧拉角 Euler Angle

    • transform.eulerAngles=new Vector3(0,45,0);
    • transform.localEulerAngles=new Vector(0,45,0); 一般使用这个
float rotateSpeed=30;
Vector3 angles=this.transform.localEulerAngles;
angles.y+=rotateSpeed*Time.deltaTime;
this.transform.localEulerAngles=angles;

相对旋转

Rotate() 旋转一个相对的角度transform.Rotate(dx,dy,dz,space)

float rotateSpeed=30;
this.transform.Rotate(0,rotateSpeed*Time.deltaTime,0.Space.Self);

当父物体转动时,带动子物体一并旋转。

生命周期

常见的生命周期消息函数

  • Awake 初始化,仅仅执行一次
  • Start 初始化,仅仅执行一次(script被禁用则不触发)
  • Update 帧更新,每帧调用一次
  • OnEnable 每当组件启用时调用
  • OnDisable 每当组件禁用时调用
  • 脚本生命周期流程图

    优先级

    默认单个周期内物体没有优先级,都是0

  • Awake

    • script1.Awake(),scirpt2.Awake()
  • Start

    • script1.Start(),scirpt2.Start()
  • Update

    • script1.Update(),scirpt2.Update()

    优先级设定:

  • 选中一个物体,打开Execution Order
  • 点+,添加一个脚本
  • 指定优先级,值越小,优先级越高

    • 或者直接拖动调节顺序

    image.png

    主控脚本

    游戏的主控逻辑

添加MainLogic.cs到新建的空物体上,设置优先级

脚本参数

  • 参数必须为public,才可以在检查器中显示
  • 参数的名称,即变量名

    • rotateSpeed->Roate Speed
  • 参数的默认值|初始值,即变量的默认值

    • 可以Reset菜单重置
  • 参数的工具提示,可以用Tooltip()指定

    • [Tooltip("旋转角速度")]

    脚本参数的赋值(以下按时间顺序)

  • 定义默认值

    • Public float rotateSpeed=30f
  • 在检查器中赋值

    • script.rotateSpeed=180f //由unity框架对参数赋值
  • 在awake中初始化
  • 在start中初始化

    值类型

    参数的类型,分为值类型、引用类型

  • 值类型(struct):如Vector3,Color

    • 本身是一个值,可直接复制
    • 若为赋值,则默认0
    • 不能为null
  • 引用类型(class):如GameObject,Transform,MeshRenderer

    • 节点 GameObject
    • 组件 Transform,MeshRenderer,AudioSource
    • 资源 Material, Texture, AudioClip
    • 数组类型
    其实在c#里面 int float 本质也是struct类型
    String 原则上属于class类型

    参数的保存

  • 在Play Mode 下,组件Copy Component
  • 在Edit Mode 下,组件Pate Component Values
    image.png
    image.png

    鼠标键盘输入

    if(Input.GetMouseButtonDown(0)){
      //点击鼠标左键
    }
    
    if(Input.GetKeyDown(KeyCode.W)){
      //按W键
    }
    if(Input.GetKeyDown(KeyCode.Space)){
      //按空格
    }

    音乐播放

  • Play On Wake
  • 代码

    • 获取AudioSource组件

      • AudioSource audio = this.GetComponent<AudioSource>();
    • 播放

      • audio.Play();
    void PlayMusic(){
      AudioSource audio = this.GetComponent<AudioSource>();
      if(audio.isPlaying){
          audio.Stop();
          //audio.loop
          //audio.mute
      }else{
          audio.Play();
      }
    }
  • 组件参数

    • AudioClip 音频资源
    • Mute 是否静音
    • Loop 是否循环播放
    • Volume 音量

    引用别的组件

  • 第一种

    • public GameObject node;
    • AudioSource audio = node.getComponent<AudioSource>();
  • 第二种

    • public AudioSource bgm

    消息调用

    SendMessage 以‘消息’的形式来调用另一个组件

    //找到目标节点
    public GameObject target;
    //向目标节点发送消息
    target.SendMessage(methodName,value);

    SendMessage内部执行(反射)

  • 找到target下所有组件
  • 在组件下寻找methodName函数

    • 若存在,则调用
    • 若无法匹配,则报错获

    取物体

  • 按名称、路径获取(不推荐)

    • GameObject flag=GameObject.Find("旋翼")
    • 最好指定全路径"无人机/旋翼"
  • 引用获取

    • 添加一个变量,在检查器引用目标
    • public GameObject node;

    父子物体

    获取父

    Transform parent=this.transform.parent;

  • 获取父节点
    GameObject parentNode=this.transform.parent.gameObject;

    获取子

    foreach(Transform child in transform{
      Debug.Log(chid.name);
    }
    Transform child= this.transform.GetChild(0);
    Transform chikld=this.transform.Find("aa");
    Transform chikld=this.transform.Find("bb/cc");
    Transform chikld=this.transform.Find("/dd");//表示根下

    设置父

  • this.transform.SetParent(other)
    设为一级节点
  • this.transform.SetParent(null);
  • 其中,parent为null表示一级节点(没父)

    显示隐藏

  • child.gameObject.SetActive(false)

    资源使用

    脚本中使用资源

  • 添加变量public AudioClip audioSuccess
  • 引用音频资源
  • AudioSource audioSource=GetComponent<AudioSource>();
  • 使用audioSource.PlayOneShot(audioSuccess) 播放

    资源数组

    public AudioClip[] songs;
    songs.Length;
    Random.Range(min,max);//用于在[min,max)中随机抽取一个数,不含max
    public class SimpleLogic:MonoBeHaviour{
      public Material[] colors;
      int m_index=0;
      void Start(){
      }
      void Update(){
          if(Input.GetMouseButtonDown(0)){
              ChangeColor();
          }
      }
      private void ChangeColor(){
          m_index+=1;
          if(m_index>=this.colros.Length){
              m_index=0;
          }
          Material selected = this.colors[m_index];
          MeshRenderer rd=GetComponent<MeshRenderer>();
          rd.material=selected;
      }
    }

    定时调用

    定时调用Invoke*,即定时器

继承自MonoBehaviour:

  • Invoke(func,delay)在delay之后执行,只调用一次
  • InvokeRepeating(func,delay,interval)在delay之后执行,每interval执行一次
  • IsInvoking(func)是否正在调度中
  • CancelInvoke(func)取消调用、从调度队列中移除
    Unity引擎核心是单线程的
  • 获取当前线程号

    using System.Threading;
    int threadId=Thread.CurrentThread.ManagedThreadId

    向量

    Vector3 (x,y,z)

  • 单位向量: 长度为1
  • 标准化 Normalize: 缩放一个向量,使其长度为1

    Vector3 v1=new Vector3(2,2,0);
    Vector3 v2=v1.normalized;
    Debug.log(v2.ToString("f3"));

    几个常量

  • Vector3.zero (0,0,0)
  • Vector3.up (0,1,0)
  • Vector3.right (1,0,0)
  • Vector3.forward (0,0,1)
    向量运算:
  • 加法 a+b
  • 减法 a-b
  • 标量乘法 b=a*2
  • 点积 c=Vector3.Dot(a,b)
  • 差积 c=Vector3.Cross(a,b)
  • 不能设null,默认是(0,0,0)
    向量测距:Vector3.Distance(a,b) 轴心点距离

    Vector3 p1=this.transform.position;
    Vector3 p2=target.transform.position;
    Vector3 direction=p2-p1;
    float distance=direction.magnitude

    预制体

    Prefab, 预先制作好的物体,可以提高开发效率

    创建

  • 先制作好一个样本节点
  • 做好后直接拖到Assets窗口,则自动生成一个prefab资源
  • 原始物体不再需要,可删

    导出

    image.png

    实例

    Prefab Instance 和原始Prefab之间存在关联
    特征:

  • 在层级窗口中,节点图标不同
  • 在层级窗口中,右键菜单/Prefab
  • 在检查窗口中,上下文工具/Prefab
    解除关联:
  • 在层级窗口中,右键菜单 Prefab/Unpack

    编辑

    prefab 相当于一个模板,可以再次编辑

单独编辑:

  • 双击Prefab进入单独编辑模式
  • 编辑节点和组件
  • 退出,完成编辑
    原位编辑
  • 选择Prefab Instance
  • 在检查器中Open
  • Content显示Normal/Gray/Hidden

    • 此时,仅选中的物体被编辑,其余物体是陪衬
  • 编辑节点
  • 退出,完成编辑

    动态创建实例

    Object.Instantiate(original,parent)
    演示:

  • 准备prefab,添加脚本
  • 添加变量 public GameObject bulletPrefab;
  • 克隆实例

    GameObject node= Instantiate(bulletPrefab,null);
    node.transform.position = Vector3.zero;
    node.transform.localEulerAngles = Vector3.zero; 

    初始化

    创建Prefab Instance之后,应做初始化:

  • Parent 父节点
  • position/localPosition 位置
  • eulerAngles/localEulerAngles 旋转
  • Script 自带的控制脚本

    销毁

    object.Destroy(obj)用于销毁一个实例

对于子弹来说

  • 当飞出屏幕时,销毁
  • 按射程 / 飞行时间
  • 当击中目标时,销毁

    碰撞检测

    image.png

private void OnTriggerEnter(Collider other){
    if(other.name.StartsWith("xxx"){
        Destory(this.gameObject);
        Destory(other.gameObject);
    }
}

seasonley
607 声望693 粉丝

一切皆数据