Unity5权威讲解 笔记

本书为TPS案例

Tricks

  1. CTRL+D 复制预设,按住V可以边缘对齐
  2. 2.

Recommends

  1. 双击Hierarchy View上的对象后,可以快速定位,或者按F,最终移动的对象可以按两次F
  2. 转换工具快捷键Q, W, E, R, T
  3. 枢纽/中心转换Z,局部/全局转换X
  4. GameObjects.Find()一般比较慢,最好不要在Update函数里面调用

Warning

  1. 工程路径不可以有中文
  2. 依据游戏设备频率调用update,在Awake中得到transform组件后再在update里面调用。

Notes

Unity界面/准备游戏开发

场景视图的绘制

模式 内容
Shaded 3D模型表面附着纹理
Wireframe 消除纹理,仅呈现3D模型的Mesh
Shaded Wireframe 同时呈现阴影和网格
Miscellaneous 混合模式,Shadow Cascades, Render Paths, Alpha Channel, Overdraw, Mipmaps
Deferred 只看到过滤后的Albedo, Specular, Smoothness以及Normal纹理
Global Illumination

开发流程

  1. 设置游戏开发环境
  2. 下载安装游戏需要的资源
  3. 设计游戏场景
  4. 构建主人公的移动和攻击
  5. 构建怪兽及其攻击
  6. 构建主人公与怪兽之间的攻击和受袭
  7. 构建游戏管理员
  8. 画面分离与合并

制作游戏场景

Floor

位置

  • Plane/Cube/Quad, 设置Rotation x=90,Scale x = y = 50
  • Floor的y坐标为0可以导出以地面为基准模型位置

纹理

  • 纹理Texture是3D模型表面的图像文件
  • 材质Material用于设置纹理属性(何种纹理,纹理间隙,模型表面特性)
  • 使用方法:创建材质并为其设置纹理,这里Shader为Standard,将纹理拖拽至Albedo插槽
  • 修改材质的Tiling可以变更纹理重复次数

Wall

Prefab

新建一个物件而后拖到Project里面

Light

种类 效果
平行光 Y轴通常为100,不受位置影响
点光源 Range属性改变照射范围
聚光灯 圆锥形的光
区域光 一般是四边形,烘焙后才能呈现,不是实时的

sky

  • 天空表现方式为skybox,skydome
  • 程序天空和可以自行设置天空颜色,大气浓度,亮度,太阳位置以及大小
  • 6面天空盒会消耗6次渲染资源,其他只有1次

主人公

组件编程

  1. 新建空游戏对象,将playerModel作为子对象,这样调整子对象形状位置方向不会影响父对象。如子弹预设方向朝下。

角色移动

方向输入

float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");

移动

void Start(){
    tr = GetComponent<Transform>();
}

void Update(){
    tr.Translate(Vector3.forward * movespeed * v * Time.deltaTime, Space.Self);
    // tr.position += new Vector3(0,0,1);
}

相机追踪

  1. Vector3.Lerp(起始位置,结束位置,浮点格式时间)线性内插平滑
  2. 使用LateUpdate,保证摄像机移动在角色移动之后
// 1. control height & dist
tr.position = Vector3.Lerp(tr.position, 
        targetTr.position - (targetTr.forward * dist) + (Vector3.up * height), 
        Time.deltaTime * dampTrace);
// 2. look at object
tr.LookAt(targetTr.position)

动画

Animation组件是Unity将动画类型设置为Legacy动画系统时自动添加的组件,保存了相应游戏模型包含的动画片段列表,不存在于该列表的动画将不会运行。

// p104
[System.Serializable]
public class Anim{
    public AnimationClip idle;
}

public class PlayerCtrl: MonoBehaviour{
    public Anim anim;
    public Animation _animation;
    void Start(){
        _animation = GetComponentInChildren<Animation>();
        _animation.clip = anim.idle;
        _animation.Play();
    }

    void Update(){
        if(v >= 0.1f){
            _animation.CrossFade(anim.runForward.name, 0.3f);
        }
    }
}

阴影

Directional Light->Shadow Type

子弹

碰撞感知

  1. 发生碰撞的两个游戏对象都要添加Collider组件
  2. 两个游戏对象中移动的一方必须有Rigidbody

Rigidbody

物理模拟,不必直接修改Position

属性 含义
Mass 相对质量
Drag/Angular Drag 摩擦系数,旋转摩擦系数
Use Gravity 重力
is Kinematic 勾选则不受物理引擎影响
Interpolate,Extrapolate
Collisition Detection Discrete->Continuous->Continuous Dynamic
Freeze Position/Rotation 阻止某一个方向改变

Collider

名称 含义
Box Collider 最常用的
Sphere Collider 最快的
Capsule Collider 人形
Mesh Collider 精细
Wheel Collider 车轮
Terrain Collider 地形

相应函数

  • 碰撞时候会触发OnCollisionEnter,OnCollisionStay,OnCollisionExit
  • Trigger会触发OnTriggerEnter,OnTriggerStay,OnTriggerExit

Tag

void OnCollisionEnter(Collision coll){
    if(coll.collider.tag == "BULLET"){
        Destroy(coll.gameObject);
    }
}

生成子弹

public class FireCtrl:MonoBehaviour{
    public GameObject bullet;
    public Transform firepos;

    void CreateBullet(){
        Instantiate(bullet, )
    }
}

怪兽

Animator/Mecanim动画控制器

  • FSM
  • 自动机循环只需要双击状态,而后选择loop,apply即可.
  • Monster/Rig选项卡->Humanoid

追击/导航

  • Floor设置为NAVigation Static,点击bake进行烘焙
  • 添加NavMeshAgent使其可以追踪玩家

    • Stopping Distance: 追击一段距离后停止
    • 给玩家设置Tag,得到怪兽追踪对象
    • 使用Coroutine进行定时判断

      void Start () {
          StartCoroutine(this.CheckMonsterState());
          StartCoroutine(this.MonsterAction());
      }
      
      IEnumerator CheckMonsterState(){
          while(!isDie){
              yield return new WaitForSeconds(0.2f);
          }
      }
    • 使用enum进行状态表示

  • 追踪

    void Start () {
        nvAgent = this.gameObject.GetComponent<NavMeshAgent> ();
        //nvAgent.destination = playerTr.position;
        animatior = this.gameObject.GetComponent<Animator>();//要在开启协程之前
    }
    
    IEnumerator MonsterAction(){
        while(!isDie){
            switch(monsterState){
                case MonsterState.idle: 
                    nvAgent.Stop();
                break;
    
                case MonsterState.trace: 
                    nvAgent.destination = playerTr.position;
                    nvAgent.Resume();
                break;
                case MonsterState.attack:
                    nvAgent.Stop();
                    break;
            }
            yield return null;
        }
    }

血迹效果

添加RigidBody和Collision,在coll位置添加血迹

GameObject blood1 = (GameObject) Instantiate(bloodEffect, coll.transform.position, Quaternion.identity);
Destroy(blood1, 2.0f);

怪兽主角通信

SendMessage

void PlayerDie(){
    GameObject[] mosters = GameObject.FindGameObjectsWithTag("monster");
    foreach(GameObject monster in mosters){
        monster.SendMessage("OnPlayerDie", SendMessageOptions.DontRequireReceiver);
    }
    Debug.Log("END");

}

delegate

//playerCtrl
public delegate void PlayerDieHandler();
public static event PlayerDieHandler OnPlayerDie;
if(hp <= 0){
    OnPlayerDie();
}
//monsterCtrl
void OnEnable(){
    PlayerCtrl.OnPlayerDie += this.OnPlayerDie;
}
void OnDisable(){
    PlayerCtrl.OnPlayerDie -= this.OnPlayerDie;
}

UGUI

  • Image
  • Button
  • Text
  • Scroll Rect

Canvas

  • 所有游戏界面UI元素必须位于Canvas下
  • 可以导入其他Canvas作为当前的子节点
  • 自动生成EventSystem
  • 按钮逻辑只需要创建一个空对象挂载一个obj即可.

- 外部修改使用gameUI = GameObject.Find("GameUI").GetComponent<GameUI>()

游戏设计

单例模式

public static GameMgr instance = null;
void Awake(){
    instance = this;
}

取代每次都要先访问挂载对象才能访问类.

对象池

如果在移动平台动态生成对象或者预设,设备负荷会非常高,应该先start生成而后直接取用.

using System.Collections.Generic;// List

public List<GameObject>monsterPool = new List<GameObject>();
for(int i = 0; i < maxMonster; ++i){
        GameObject monster = (GameObject)Instantiate(monsterPrefab);
        monster.name = "Monster_" + i.ToString();
        monster.SetActive(false);//先设置为false
        monsterPool.Add(monster);
    }
//
if(isGameOver) break;
foreach(GameObject monster in monsterPool){
    if(!monster.activeSelf){
        int idx = Random.Range(1,points.Length);
        monster.transform.position = points[idx].position;
        monster.SetActive(true);
        break;
    }
}
// 然后在怪兽挂掉的地方添加一个协程放回对象池.
阅读更多
上一篇Effective C++ 笔记
下一篇Unity Manual 笔记
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭