# Unity 引擎入门实践

关键词:Unity / 入门 / 游戏对象 / 场景 / 快捷键 / Terrain / 资源包

1. 游戏对象和基本操作 #

1.1 场景和游戏对象 #

               游戏项目
                  |
                /   \
              场景A  场景B ... ...
                |
            /       \
        游戏对象1   游戏对象2 ... ...
           |
         /   \
       组件  组件 ... ...

场景显示在 Scene 里面,Hierarchy 里面是游戏对象比如 3D Object: Main Camera、Plane等;
按住 Q/W/E/R/T 同时点击鼠标操作:Q平移场景/W平移选中的游戏对象/E旋转/R缩放工具/T操作2D的精灵工具,分别对应 Unity 编辑器左上角的功能图标的快捷键;
鼠标右键:移动视图;

[游戏对象]

  • 一个游戏项目由多个场景组成,在场景中,一个角色,一个模型,一个特效,都是游戏对象。
  • 场景就是由多个游戏对象组成的;
  • 每个游戏对象身上都会有多个组件,使游戏对象具备相应的特性、实现相应的功能;

1.2 快捷键操作 #

  • 选中任何游戏对象,按F键或者双击,都可以定位到该游戏对象;
  • 按下鼠标右键 + WASD 键进行场景漫游;
  • 按下 Alt + 鼠标左键旋转视角;
  • 按下鼠标右键旋转视角;
  • QWERT工具分别是手型工具、平移工具、旋转工具、缩放工具和 2D 工具;

1.3 Terrain 地形系统 #

  • 提升/下沉地形工具
  • 平坦地形工具
  • 平滑地形工具
  • 植树工具
  • 地表细节工具

从网上找一些地形贴图资源,自己使用地形编辑器编辑一个新的地图;

1.4 资源包的导入 #

.unitypackage 后缀文件

1.5 摄像机 #

在Unity中摄像机决定游戏最终的显示效果
同一个场景中允许存在多个摄像机

1.6 世界坐标系和本地坐标系 #

世界坐标 Global 是整个 3D 场景的坐标系;
本地坐标 Local 是某个游戏对象内独立的坐标系;
(游戏对象可以有子对象,世界坐标与本地坐标是相对的)

1.7 网格

要想让模型出来,网格是必须的(好比人的骨架);

1.8 纹理

使模型表面赋有更多的细节,就需要给它添加纹理;
比如:在Assets中新建一个material材质球 拖拽到 Object 上,通过右侧的面板修改材质球上的纹理属性间接修改Object

1.9 材质和着色器

材质能够将纹理应用在模型上,着色器决定纹理呈现出的最终效果;


2. 工程与应用程序 #

项目目录下:
- Assets 里面存放的是项目所需要的资源;
- Library 里面存放的是所需要的库文件;
- ProjectSettings 里面存放的是工程设置文件;
- Temp 里面存放的是临时文件;

项目框架:
一个工程里面有多个场景,一个场景中有多个游戏对象,每个游戏对象又有多个组件;

                 工程(Project)  
                      |  
                    /   \  
            场景(Scene)  场景(Scene) ... ...  
                 |
              /      \  
 游戏对象(GameObject)   游戏对象(GameObject) ... ...
               |  
           /        \  
   组件(Component)  组件(Component) ... ...  

每个场景可以理解为每个界面;

组件开发:
游戏物体想要实现什么功能,只需要添加对应的组件即可,我们可以在Inspector视图中查看当前游戏对象身上的组件,修改组件的属性; (Inspector)

  • Transform 组件,决定物体的位置,旋转和缩放;
  • Mesh Filter 组件,显示网格;
  • Box Collider 组件,用来给物体添加碰撞器;
  • Mesh Renderer 组件,可以给物体添加材质,纹理以及渲染的方式;

脚本组件:
脚本也是一种特殊的组件;
创建脚本;
在脚本中设置公共字段作为组件属性;
在脚本中通过方法获取游戏对象和组件;

用Mono编辑脚本

using UnityEngine;
using System.Collections;

// 如果我们的脚本需要挂载到游戏对象身上,就需要继承于 MonoBehaviour
public class TestCS : MonoBehaviour {

    public int age;
    public string name;

    // Use this for initialization
    void Start () {
        // gameObject 表示当前脚本组件所挂载的游戏对象
        // unity 中输出到控制台使用 print 或者 Debug.log
        print ("Test 脚本挂在到了 " + gameObject.name + " 的身上");
        // 每个游戏对象上都至少有一个组件,叫做 Transform
        // transform 表示当前游戏对象身上的 Transform 组件
        print(transform.position.x);
        print(name + age);
    }

    // Update is called once per frame
    void Update () {

    }
}

运行结果:

对应的Inspector:

可以再添加一个脚本Demo.cs,修改TestCS.cs的属性,可以改变Cube的Script内容

using UnityEngine;
using System.Collections;

public class Demo : MonoBehaviour {

    // Use this for initialization
    void Start () {
        // GameObject de fangfa GetComponent, nenggou
        // huoqu dangqian youxi duixiang shenshang zhiding de leixing de zujian duixiang 
        TestCS t = GetComponent<TestCS> ();
        t.age = 24;
        t.name = "Da Wang";
        t.Log();
    }

    // Update is called once per frame
    void Update () {

    }
}

结果截图:


3. Unity 脚本 #

3.1 生命周期 #

Awake –> OnEnable –> Start
==》Update –> LateUpdate ==》
OnDisable –> OnDestroy

using UnityEngine;
using System.Collections;

// 继承于 MonoBehaviour 的类叫做运行时类,运行时类都不能手动实例化,eg:不能 new: Test t = new Test()
public class Test : MonoBehaviour
{
    // 这些方法都不是 MonoBehaviour 中定义的方法,而是通过反射调用的一些事件。方法名写错不会报错
    // 这些方法定义了一个脚本从被加载到被销毁的过程中,脚本的生命周期

    // 1.每当脚本被加载时调用,调用 1 次;在Awake中做一些初始化操作(放 public 字段);
    void Awake ()
    {
        // 初始化 public 成员    
        print ("Awake");
    }

    // 2. 在每次激活脚本的时候就会调用 OnEnable,比如计时器重置;
    void OnEnable ()
    {
        print ("onEnable");
    }

    // 2. 在第一次调用 Update 之前调用一次 Start 方法,然后中途不管激活取消激活,都不会再调用了
    // 在Start方法中也可以做一些初始化操作(主要放私有字段);
    void Start ()
    {
        print ("Start");
    }

    // 3.每帧都会调用一次 Update,每秒接近60帧,所以每秒大概调用60次左右
    void Update ()
    {
        print ("Update");
    }

    // 4. 在Update调用之后进行调用,刷新其它逻辑的时候
    void LateUpdate ()
    {
        print ("LateUpdate");
    }

    // 5. 取消激活状态后调用
    void OnDisable ()
    {
        print ("OnDisable");
    }

    // 6.被销毁时调用一次
    void OnDestroy ()
    {
        print ("OnDestroy");
    }

    // 用来写 UI 的,持续调用 - 调用频率高 IMGUI代码需要写在 OnGUI 方法中
    void OnGUI ()
    {
        print ("OnGUI");
    }

    // 以固定的频率调用(跟图像刷新无关,不受图像刷新帧速率的影响)
    // 一般把处理物理的代码放在这里
    void FixedUpdate ()
    {
        print ("FixedUpdate");
    }

}

//public class A{
//  public void T(){
//      Test t = new Test ();// wrong
//  }
//}

3.2 Input 类 #

Input 获取键盘事件:

  • Input.GetKey()
  • Input.GetKeyDown()
  • Input.GetKeyUp()
using UnityEngine;
using System.Collections;

// 继承于 MonoBehaviour 的类叫做运行时类,运行时类都不能手动实例化,eg:不能 new: Test t = new Test()
public class Test : MonoBehaviour
{
    void Start ()
    {
        // print ("Start");
    }

    // 获取用户事件需要使用 Input 类
    // GetKeyDown 按键按下 & GetKeyUp 按键弹起 & GetKey 检测持续按键的事件
    void Update ()
    {
        // 每帧都需要监听用户事件
        // 在当前这一帧中如果用户按下了 W 就会返回 true, 否则返回 false
        if (Input.GetKeyDown (KeyCode.W)) {
            print ("往前走.");
        }else if(Input.GetKeyDown(KeyCode.S)){
            // Debug.Log ("往后退.");
            print ("往后退.");// print 只能在 MonoBehaviour 的子类中使用
        }

        if(Input.GetKeyUp(KeyCode.Alpha1)){
            print ("弹起了 1 键");
        }

        if(Input.GetKey(KeyCode.F)){
            print ("按了 F 键");
        }

        // GetMouseButtonDown用来检测鼠标按键按下的事件 & 
        // 参数 0 表示鼠标左键 & 参数 1 表示鼠标右键 & 参数 2 表示中键
        if(Input.GetMouseButtonDown(0)){
            print ("按下了鼠标左键");
        }

        if(Input.GetMouseButtonUp(0)){
            print ("弹起了鼠标左键");
        }

        if(Input.GetMouseButton(0)){
            print("持续按下了鼠标左键");
        }

    }

}

结果截图:


Name Tag ActiveSelf SetActive() GetComponent() AddComponent()
GetComponent() AddComponent()
Destroy() FindGameObjectWithTag() FindGameObjectsWithTag()

3.3. GameObject #

using UnityEngine;
using System.Collections;

// 继承于 MonoBehaviour 的类叫做运行时类,运行时类都不能手动实例化,eg:不能 new: Test t = new Test()
public class Test : MonoBehaviour
{
    // GameObject - 游戏对象类
    void Start ()
    {
        // 通过 gameObject 获取当前脚本所挂载的游戏对象
        // 一般来说, 在属性视图中能够看到或修改的属性, 也能够在脚本中进行获取并且修改

        // 1. 获取 & 设置游戏对象的名字
        print ("gameObject.name => " + gameObject.name);
        gameObject.name = "小胡 Cube";
        print ("经修改的 gameObject.name => " + gameObject.name);

        //2. 获取 & 设置游戏对象的 Tag
        print ("gameObject.tag => " + gameObject.tag);
        gameObject.tag = "Player";
        print ("经修改的 gameObject.tag => " + gameObject.tag);

        // 3. 获取 & 设置当前游戏对象的激活状态
        print ("gameObject.activeSelf 是否激活 => " + gameObject.activeSelf);
        gameObject.SetActive (false);
        print ("经重置的 gameObject.activeSelf 是否激活 => " + gameObject.activeSelf);

        // 4. 获取游戏对象身上的组件 eg: transform
        // 在 Test.cs 中获取 CubeController 组件
        CubeController c = gameObject.GetComponent<CubeController> ();
        print (c.balabala); // 获取组件
        Light l = gameObject.AddComponent<Light> (); // 添加组件

        // 5. 通过 tag 的值查找游戏对象
        GameObject g = GameObject.FindGameObjectWithTag ("Player");
        g.name = "小胡 Sphere";
        // 另一种写法
        GameObject gg = GameObject.FindWithTag ("Player");

        // 6. 通过游戏对象名查找游戏对象
        GameObject ggg = GameObject.Find ("Main Camera");
        ggg.name = "主摄像机";

        // 7. 通过 tag 值查找多个游戏对象
        GameObject[] gs = GameObject.FindGameObjectsWithTag("Player");
    }

    void update ()
    {
//      if (Input.GetKeyDown (KeyCode.S)) {
//          // 2 秒钟之后销毁游戏对象
//          GameObject.Destroy (gameObject, 2f);
//      }

    }
}
using UnityEngine;
using System.Collections;

public class CubeController : MonoBehaviour {

    public string balabala;
}




运行结果

4. Unity 常识知识点总结 #

4.1 关于程序 #

基本组成:

  1. Sence 场景,类似于 Flash 中的 stage, 用于放置各种对象
  2. GameObject, 可以携带各种 Component;

每个 GameObject 至少带有 Transform 组件, 所有的组件都可以从顶部菜单 Component 里面找到并添加给游戏对象;

脚本语言:

  • C# / Javascript / boo (前两者使用较为广泛, 网上教程以前两者为主, 个人推荐 C#),一般的继承 MonoBehavior 类的脚本都需要依附的场景中的对象上才能被执行.

GUI(用户图形界面):

  • 用于制作按钮/文本显示/滚动条/下拉框等常用图形操作界面元素,使用 GUISkin 和 GUIStyle 可以自定义样式;
  • 系统自带 GUI;
  • 各类 GUI 插件, NGUI/EZGUI 等;

预制:

  • 用于程序运行时,动态实例化对象的”母体”,比如,在射击类游戏中,子弹的生成就可以使用实例化预制的方式来实现,可以定义它的各种属性方法, 然后在使用的时候直接实例化一个实例;
  • 在 project 面板右击选择 Create -> Prefab 新建一个预制, 将 Hierarchy 面板中要制成的对象拖到这个新建预制上即可;

标签:

tag 用于辨别物体, 与 name 类似,使用对象的 tag 和 name 都可以找到对应的物体, GameObject.Find(“name”) 或 GameObject.FindWithTag(“Tag”); 默认的是 Untagged,可以通过 Inspector 面板里面 Tag 的下拉菜单选择 Add Tag 项来添加新的标签; Inspector -> TagManager -> Tags 里的 size 来增加标签的数量, 每个 Element 内都填入新标签的名字;

层:

在使用某些功能的时候, 可以通过层来过滤不需要运用该功能的对象, 也就是把该功能运用到特定的层, 比如, 相机的 Culling Mask 属性, 通过选择特定层可以实现只显示位于被选中的层的对象.
层的添加也是在标签管理器中, Unity 已经设置了8个层,你是不能对这8个层进行修改的,你可以从第9个(也就是 user layer8)开始添加你定义的层;

资源:

  • .unitypackage 格式的文件可以直接 import 到 unity 中,记住最好是在打开 unity 的情况下,在 project 面板里右击,然后在 import packages 中选中你要导入的资源;
  • 可以 export package 导出场景成为 .unitypackage 资源包
  • 在工程面板可以 import new assests 可以导入其他形式的资源, 如, 模型/音频/视频等, 也可直接从外部文件夹中拖入

    物理引擎:

    unity 使用 nvidia PhysX 物理引擎

  • 碰撞器: 各种基本体的碰撞器(box/sphere/capsule/cylinder), 网格碰撞器(mesh collider),车轮碰撞器(Wheel collider),地形碰撞器(terrain collider) 碰撞器组件在你选中对象的时候会以绿色框显示;

  • 碰撞检测: 碰撞器碰撞检测 / 光线投射(射线) / 触发器碰撞检测, 通过碰撞检测可以得到与当前对象发生碰撞的对象信息, 使用碰撞的相关函数 OnCollisionEnter(碰撞器碰撞检测) / OnTriggerEnter(触发器碰撞检测) / Physics.Raycast(光线投射)获取;
  • 刚体: 模拟物体物理现象的基础, 加了刚体组件才能模拟重力 / 阻力等;
  • 力: 作用于刚体,你只要通过添加各种力, 就可以使刚体表现出跟现实中一样的受力情况;

    粒子系统:

  • 两种形式, 一种以物体携带例子系统组件的形式实现, 另一种是直接使用粒子系统 GameObject(3.5 以后)

  • 粒子系统 GameObject: GameObject – Create Other – Particle System
  • 粒子系统组件: 粒子发射器(Particle Emitter, 有 Ellipsoid Particle Emitter 和 Mesh Particle Emitter 两种类型的粒子发射器, 主要有 粒子产生 / 数量 / 速度 / 大小 / 存活时间等参数设置), 粒子动画器(Particle Animator, 主要负责粒子产生后直至粒子消亡的行为变化的控制, 包括运动过程中的旋转 / 受力等), 粒子渲染器(Particle Renderer, 主要是负责给予粒子的渲染,阴影,材质等设定)

    Camera(相机):

  • 相机视角: 透视(可调整透视角度) / 正交(没有透视效果)

  • Skybox: 只在 Game 窗口可见, 需要 skybox 类型的 shader, 以及附在其上的六面贴图纹理
  • 第一人称视角: 角色不出现在视野中, 相机看到的就像角色双眼看到的一样
  • 第三人称视角: 能在视野中看到角色, 相机一直跟着角色运动.
  • 可以使用导入 Unity 自带的 Character Controllers 资源包, 里面有第一人称和第三人称的原型

    光照系统:

    • 常见灯光类型: 平行光(Directional light, 无衰减, 模拟太阳光)
    • 聚光灯(spotlight, 从一点向某一方向反射锥形光束, 有衰减, 聚光效果)
    • 点光源(Point light, 从一点向外辐射, 有衰减)
    • 烘焙: 将静态光影效果渲染到纹理上, 减少灯光和阴影带来的开销
    • 阴影: 分为 hard shadows 和 soft shadows 两种, 前一种阴影比较重, 后一种相对柔和.
    • 要产生阴影,还需要将投射阴影的对象的 Cast shadows 都选, 将接受阴影的对象的 Receive shadows 勾选, eg: 你要让树在地面上产生阴影, 那就得让树投射阴影, 然后让地面接受阴影才行;

地形系统:

选择顶部菜单 Terrain – creat terrain 创建一个地形
地形有一组地形工具用来绘制地形的高度, 生成各种地貌, 并且可以对地表运用纹理, 还可以添加树,草等地表植被.

4.2 关于美术 #

3d 模型 / 材质 / 纹理(贴图)
shader(着色器, Unity 本身拥有几十种 shader, 也可以根据自己的需要使用 shaderLab 语言来编写 shader,一般可以只用 Unity 自带的和网上流传的)

4.3 关于发布 #

关于 Player settings 播放器设置的话这里暂且不多说,发布的时候通过 player setting 进行发布设置,每个平台都有对应的设置参数,根据需要来设置,主要 是关于程序图 标、分辨 率、渲染 等设置, 大家可以 自己试试 (有些参 数只有 pro 版才能设置)。
下面我们来看看 build settings 对话框,左侧是可发布的平台(Unity 跨平台性 很强大,4.0 已支持发布至 10 种平台:IOS、Andriod、Windows、Mac、Linux、 Webplayer、Flash、PS3、Xbox360、Wii u),右侧是对应平台的发布设置,一 般初学的话,只要会发布单机版的和 webplayer 的就差不多了,这两个的话, 右侧的发布选项按照默认的设置就可以,当然单机版要在 Target Platform 中选 择对应的操作系统,webplayer 的话这里我给大家介绍前两个参数,Streamed 顾名思义就是在网络上下载的时候以流的形式,Offline Deployment,这个是 可以在离线(断网)状态下本地运行你的 webplayer 程序(这里需要注意的是, 默认情况下你每次打开 webplayer 程序的时候,浏览器都会自动去访问官网更 新 webplayer 插件,如果你没勾选这个选项而又在没有联网的状态下运行 webplayer 的话是无法运行的)

End.

Note by HF.


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值