关键词: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 关于程序 #
基本组成:
- Sence 场景,类似于 Flash 中的 stage, 用于放置各种对象
- 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.