Unity
1.基本介绍
1.1Unity的安装与汉化_引擎安装与基础操作
安装时先安装Unity Hub,再安装Unity.
汉化在Unity Hub的Installs中找到对应版本的Unity,左上角的设置按钮,在跳出的窗口选择中文包,下载安装好后进入Unity,在Edit>Preferences>Languages>Editor Languages中选择中文版本。
1.2Unity窗口界面介绍与布局
2.2.1Scene界面
1.鼠标右键旋转视角
2.按住鼠标滚轮移动视角
3.旋转鼠标滚轮调整远近视角
4.按住右键并按WASD可以在场景中进行漫游
5.Pivot和Center
Pivot表示轴心,在该状态下,点击父物体时坐标会落在父物体上,旋转时也是子物体围绕父物体旋转。
Center表示中心,在该状态下,点击父物体时坐标会落在父物体与其所有的子类物体(包括孙物体和后面的物体)的中心点,旋转时也会围绕该中心点旋转。
6.Global和Local
Global表示全局,在该状态下,旋转后物体的坐标方向会与原始的坐标方向一致。
Local表示局部,在该状态下,旋转后物体的坐标会保持旋转后的方向。
2.2.2Project界面
选择文件并右键点击Show in explorer可以打开所在文件夹
1.3Unity菜单
Fils,Edit,Assets,...等菜单的功能。
2.游戏流程控制与脚本基础
2.1脚本生命周期
2.1.1方法名
示例
using UnityEngine;
public class Test : MonoBehaviour
{
/*游戏开始时调用,在脚本组件未勾选的情况下也可运行。*/
void Awake()
{
Debug.Log("Awake");
}
/*当物体被启用时调用*/
void OnEnable()
{
Debug.Log("Enable");
}
/*没有Reset方法的情况下,会在执行OnEnable方法后执行*/
void Start()
{
Debug.Log("Start");
}
/*每帧调用一次,一般用于非物理运动,例如游戏的逻辑。*/
int updateCount = 0;
void Update()
{
Debug.Log("Update第" + UpdateCount++ + "次打印");
}
/*以相同的时间间隔调用,用在力学更新效果中。*/
int fixedUpdateCount = 0;
void FixedUpdate()
{
Debug.Log("FixedUpdate第" + FixedUpdateCount++ + "次打印");
}
/*在Update和FixedUpdate调用后调用。*/
int lateUpdateCount = 0;
void LateUpdate()
{
Debug.Log("LateUpdate第" + LateUpdateCount++ + "次打印");
}
/*当物体被禁用时调用*/
void OnDisable()
{
Debug.Log("OnDisable");
}
/*当物体销毁后执行*/
void OnDestroy()
{
Debug.Log("Ondestroy");
}
}
该段代码的功能是,通过控制台打印观察方法的执行顺序
2.1.2检测调用间隔时间
使用的API:Time.deltaTime;
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
Debug.Log("Update"+Time.deltaTime);
}
}
该脚本实现的功能是每帧输出一次文字Update和每帧的间隔时间。
2.2变量的创建与使用
2.2.1变量的创建
变量在类下面直接创建,默认为私有,如为私有可省略Private.
2.2.1变量的操作
1.隐藏Publicb变量
在变量上方用 [HideInInspector]
示例
using UnityEngine;
public class Test : MonoBehaviour
{
[HideInInspector] //序列化 隐藏
public int num;
}
2.显示private变量
在变量上方用[SerializeField]
示例
using UnityEngine;
public class Test : MonoBehaviour
{
[SerializeField] //序列化 显示
private int num;
}
3.设置变量范围
在变量上方用[Range(a,b)]
示例
using UnityEngine;
public class Test : MonoBehaviour
{
[Range(1, 100)]
public int num;
}
3.游戏素材与脚本
3.1游戏素材
游戏素材包括字体,图片,音频,视频,模型,场景,粒子特效等。
素材的添加可以通过在Project中点击右键选择Import New Assets或Import Package实现,也可以通过文件夹拖入的方式实现。
3.2游戏脚本
游戏脚本可以通过在Project中点击右键Create>C# Script创建。
游戏脚本需要挂载到物体上方能实现其功能。
游戏脚本命名不能加空格,否则无法挂载。
4.游戏物体
4.2物体的标签和层级
标签可以方便查找物体。
层级可以运用在一些操作上,比如Camera中Inspector中的Culling Mask上,可以通过勾选掉一些层级来屏蔽显示一些物体
4.3摄像机
组件Camera>Projection下的persepective表示透视,透视模式下可以通过Field in view调镜头的角度;另一个Orthography表示正交即在播放时场景没有透视效果。
组件Camera>Clipping Planes为视距设置选项,在视距范围之外(高于最远视距,低于最近视距)的物体无法被摄像机看到。
4.4预制件
4.4.1克隆预制件
使用的API:GameObject.Instantiate(变量名);
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = Resources.Load<GameObject>("Cubes/Cube");
GameObject.Instantiate(go);
}
}
在Project中新建Resources文件夹,在Resources文件夹下新建Cubes文件夹,将Hierachy中做好的物体Cube拖入Cubes文件夹中,制成预制件。该段代码实现的功能是:在运行时将Resources/Cubes文件夹中的Cube预制件克隆一份并显示。
4.4.2修改预制件
预制件的修改的两种方式;
第一种:在Project中双击预制件,或者在Hietachy中点击其中一个预制件的最后的“>”标志,进入预制件修改视图,在修改视图中进行预制件的修改。
第二种:在Hierachy中选择一个预制件,直接进行修改,修改后再单击Hierachy中的预制件,在Inspector中找到Override按钮,点击按钮并选择Apply All即可完成对预制体的修改。预制件的Inspector中的组件参数修改后会留下标记,在标记行点击鼠标右键会出现Apply to prefab”/*预制件名称*/”的提示框,点击即将修改应用至预制件。
4.5通过脚本操作物体
4.5.1查找物体
1.按照路径查找物体
使用的API:GameObject.Find(物体的Hietachy路径);
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
go.SetActive(false);
}
}
在Hierachy中新建一个物体Cube,在Cube下新建一个子物体Sphere,将含上面代码的脚本挂载到某一物体上,可以实现在运行时隐藏物体Sphere,若一个文件夹下有同名的多个物体,则查找到的物体为创建时间最短的物体。
2.按照标签查找
使用的API:GameObject.FindGameObjectWithTag("标签名");
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.FindGameObjectWithTag("Player");
go.SetActive(false);
}
}
该段代码的功能是找到最后将标签设置成Player的物体,并在运行时隐藏该物体。
4.5.2修改物体名称
使用的API:物体名.name=”修改后物体名称”;
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
go.name = "CuteSphere";
}
}
该段代码功能是找到物体Sphere,并在运行时将该物体名称改为CuteSphere。
4.5.3修改物体位置
使用的API:变量名.transform.position=/*更改后的位置*/
示例:
using UnityEngine;
public class Temp : MonoBehaviour
{
public GameObject cube;
void Start()
{
cube.transform.position = new Vector3(2, 1, 3);
}
}
该段代码功能是,将物体的位置移动到世界坐标(2,1,3)的位置。
如果是想让物体移动到相对坐标(2, 1, 3)的位置,可将代码cube.transform.position = new Vector3(2, 1, 3);写成cube.transform.localposition = new Vector3(2, 1, 3);
如果想让找到的物体在运行时旋转一定角度,可以将上面示例中的代码cube.transform.position = new Vector3(2, 1, 3);写成go.transform.Rotation= Quaternion.Euler(new Vector3(a, b, c))或cube.transform.eulerAngles = new Vector(a,b,c))/*a,b,c表示旋转角度*/;
如果想让找到的物体在运行时放大或缩小,可以将上面示例中的代码cube.transform.position = new Vector3(2, 1, 3);写成cube.transform.localScale = new Vector3(a,b,c))/*a,b,c表示放大倍数*/;
4.5.4删除物体
使用的API:Destroy( );
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
Destroy(go);
}
}
该段代码功能是找到物体Sphere,并在运行时删除该物体。
如果想实现在运行后5秒消除,可以将代码Destroy(go);修改为Destroy(go,5);。
如果想让物体在切换场景的时候不销毁,可以将Destroy(go);修改为DontDestroyOnLoad(go);。
4.5.5克隆物体
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
public GameObject Cube;
void Start()
{
GameObject.Instantiate(Cube);
}
}
将含上面代码的脚本挂载到某一物体上,并将需要克隆的物体Cube拖入脚本组件中,运行后便可在场景中得到一个克隆的预制体Cube。
5.物体组件
5.1组件的基本操作
代码类名后面跟的MonoBehaviour使脚本能够挂到物体的组件中。
组件在Inspector视图中,可以通过最下面的Add Component添加组件,通过组件点击组件名左边的勾选符号打开或关闭组件,通过组件名右边的三个点下面的Remove Component移除组件。
5.2通过脚本操作组件
5.2.1添加组件
使用的API:AddComponent</*组件名称*/>();
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
go.AddComponent<Rigidbody>();
}
}
该段代码先找出物体Sphere,运行时在该物体上添加Rigidbody组件。
5.2.2查找组件
1.查找单个组件
使用的API:GetComponent</*组件名称*/>()
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
go.GetComponent<SphereCollider>().radius = 1;
}
}
该段代码的功能是,先查找Sphere物体,然后查找Sphere物体的SphereCollider组件,并将该组件中radios值改为1。
如果想查找该物体及其子物体的某个组件,可以将示例代码中的go.GetComponent<SphereCollider>().radius = 1;改为go.GetComponentInChildren<SphereCollider>().radius = 1;,改完之后会查找该物体及其子物体的该组件类型,找到一个后便停止,不再继续查找。
如果想查找该物体及其父物体的某个组件,可以将示例代码中的go.GetComponent<SphereCollider>().radius = 1;改为go.GetComponentInParent<SphereCollider>().radius = 1;改完之后会查找该物体及其父物体的该组件类型,找到一个后便停止,不再继续查找。
2.查找多个同类型的组件
使用的API:GetComponents<AudioSource>();
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
SphereCollider[] sphereColliders= go.GetComponents<SphereCollider>();
Debug.Log("查找到多少个:"+sphereColliders.Length);
}
}
这段代码的功能是,先找到Sphere物体,找出物体里所有SphereCollider组件,将找到的组件放入数组SphereCollider中,并通过控制台打印数组的长度。
如果想查找该物体及其子物体的某个组件,可以将示例代码中的SphereCollider[] sphereColliders= go.GetComponents<SphereCollider>();改为SphereCollider[] sphereColliders= go.GetComponentsInChildren<SphereCollider>();改完之后会查找该物体及其子物体的所有该组件类型。
如果想查找该物体及其父物体的某个组件,可以将示例代码中的SphereCollider[] sphereColliders= go.GetComponents<SphereCollider>();改为SphereCollider[] sphereColliders = go.GetComponentsInParent<SphereCollider>();改完之后会查找该物体及其父物体的所有该组件类型。
5.2.3删除组件
使用的API:Destroy(/*要删除的组件类型*/);
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
SphereCollider sphereCollider = go.GetComponent<SphereCollider>();
Destroy(sphereCollider);
}
}
该段代码的功能是,找到物体Sphere,并在运行时删除该物体的SphereCollider组件。SphereCollider sphereCollider = go.GetComponent<SphereCollider>();改为Component sphereCollider = go.GetComponent<SphereCollider>();也可实现该效果。
5.2.4关闭和激活组件
使用的API:enabled=false;
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
go.GetComponent<SphereCollider>().enabled=false;
}
}
该代码的功能是,找到物体Sphere,并在运行时关闭该物体的SphereCollider组件。
如果想要激活组件,可以将上面示例中的go.GetComponent<SphereCollider>().enabled=false;改为go.GetComponent<SphereCollider>().enabled=true;
6.场景管理
6.1场景的基础操作
6.1.1场景的创建
场景创建的快捷键Ctrl+N可以快捷创建场景,此时创建的场景为临时场景,需要保存起来后续才能使用。
6.1.2场景的删除
直接在文件夹中进行删除即可,因为场景中可能会有一些依赖项,因此非必要不要删除场景。
6.2同步加载场景
6.2.1切换场景
使用的API:SceneManager.LoadScene( );
示例:
using UnityEngine;
using UnityEngine.SceneManagement;
public class Test : MonoBehaviour
{
void Start()
{
SceneManager.LoadScene("Scenes/SampleScene1");
}
}
先将两个场景导入File>Build Settings...中,将含上面代码的脚本挂到待切换场景的一个物体上,该脚本可以实现将场景切换至Scenes文件夹下的SampleScene1场景播放;
地址"Scenes/SampleScene1"也可换成该场景在Build Settings...中所对应的序号。
6.2.2同时加载场景
使用的API:SceneManager.LoadScene( ,LoadSceneMode.Additive);
示例:
using UnityEngine;
using UnityEngine.SceneManagement;
public class Test : MonoBehaviour
{
void Start()
{
SceneManager.LoadScene("Scenes/SampleScene1",LoadSceneMode.Additive);
}
}
先将两个场景导入File>Build Settings...中,将含上面代码的脚本挂到原场景的一个物体上,该脚本可以实现将原将原场景与Scenes文件夹下的SampleScene1场景同时加载;
地址"Scenes/SampleScene1"也可换成该场景在Build Settings...中所对应的序号。
6.3异步加载场景
示例
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Test : MonoBehaviour
{
void Start()
{
StartCoroutine(Load());
}
private IEnumerator Load()
{
AsyncOperation asyncOperation=SceneManager.LoadSceneAsync("Scene/Cut");
asyncOperation.allowSceneActivation = false;
while (asyncOperation.progress < 0.9f)
{
Debug.Log("Current progress is " + asyncOperation.progress);
yield return null;
}
asyncOperation.allowSceneActivation = true;
if (asyncOperation.isDone)
{
Debug.Log("Finished load and skip.");
}
else
{
Debug.Log("Not finished");
}
}
}
不理解该段代码
6.4加载场景时保留物体
使用的API:DontDestroyOnLoad( );
示例:
using UnityEngine;
using UnityEngine.SceneManagement;
public class Test : MonoBehaviour
{
void Start()
{
GameObject capsule = GameObject.Find("Capsule");
DontDestroyOnLoad(capsule);
SceneManager.LoadScene("Scenes/SampleScene1");
}
}
先将两个场景导入File>Build Settings...中,将含上面代码的脚本挂到原场景的一个物体上,该脚本实现的功能是将原场景切换至Scenes文件夹下的SampleScene1场景后保留原场景的Cube物体及该物体下面的子物体,该代码保留的物体只能是根物体,即没有父物体的物体。
地址"Scenes/SampleScene1"也可换成该场景在Build Settings...中所对应的序号。
7.UGUI图形系统
7.1画布与事件系统
7.1.1画布
画布用于承载所有的UI元素。
Canvas物体的Canvas组件Render Mode分为三种:
第一种:Screem Space Overlay模式,该模式下画布中的元素始终在前面。
第二种:Screem Space Camera模式,该模式下画布中的元素是否在前取决于它与物体的位置。
第三种:World Space模式,该模式下画布可以自由移动缩放。可用来做人物的血条等。
7.1.2事件系统
事件系统是使画布内元素产生效果系统,创建画布后会自动创建,如果不小心删除也可点击添加单独创建。
7.2图像、文本框、按钮、输入框的脚本交互
7.2.1登录按钮的脚本实现
示例
using UnityEngine;
using UnityEngine.UI;
public class Login : MonoBehaviour
{
InputField accountInput;
InputField passwordInput;
Button loginButton;
void Start()
{
accountInput = transform.Find("Account").GetComponent<InputField>();
passwordInput = transform.Find("Password").GetComponent<InputField>();
loginButton = transform.Find("Login").GetComponent<Button>();
loginButton.onClick.AddListener(LoginButtonOnClick);
}
void LoginButtonOnClick()
{
string account = accountInput.text;
string password = passwordInput.text;
Debug.Log("Account is " + account);
Debug.Log("Password is " + password);
}
}
该段代码实现的功能是,在输入账号和密码并点击登录键后,将账号和密码在控制台输出。
7.2.2更换背景图的脚本实现
示例
using UnityEngine;
using UnityEngine.UI;
public class Change : MonoBehaviour
{
public Sprite bg;
void Start()
{
transform.Find("Background").GetComponent<Image>().sprite = bg;
}
}
该段代码实现的功能是,在将新的图像添加到新建的脚本后,点击播放可以在运行时将背景图换成新的图像
7.2.3修改文本框
示例
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
string text = "抵制不良游戏,拒绝盗版游戏。注意自我保护,谨防受骗上当。\n适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。";
void Start()
{
transform.Find("Text").GetComponent<Text>().text = text;
}
}
该段代码实现的功能是,在运行时将文本框文字改为:抵制不良游戏,拒绝盗版游戏。注意自我保护,谨防受骗上当。适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。
7.2.4点击按钮导入链接
示例
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
void Start()
{
transform.Find("Button").GetComponent<Button>().onClick.AddListener(ButtonOnClick);
}
void ButtonOnClick()
{
Application.OpenURL("https://v.qq.com/channel/choice?channel_2022=1");
}
}
该段代码实现的功能是,在点击了Button按钮后,跳转到网站https://v.qq.com/channel/choice?channel_2022=1。
7.3切换开关与开关组
7.3.1切换开关
示例
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
InputField user;
InputField password;
Toggle toggle;
Button logon;
void Start()
{
user= transform.Find("User").GetComponent<InputField>();
password = transform.Find("Passward").GetComponent<InputField>();
toggle=transform.Find("Toggle").GetComponent<Toggle>();
logon=transform.Find("Logon").GetComponent<Button>();
logon.onClick.AddListener(logonOnClick);
}
void logonOnClick()
{
if (toggle.isOn == true)
{
string username= user.text;
string passwordnum=password.text;
Debug.Log("用户名是:"+username);
Debug.Log("密码是:"+passwordnum);
}
else
{
Debug.Log("请先同意用户协议");
}
}
}
该段代码实现的功能是,在点击了按钮后,可以正常登录,未点击时控制台显示:请先同意用户隐私协议!
7.3.2开关组
若有多个Toogle,而只能选择一个,可在Hierachy中新建一个空对象,在空对象的Inspector中添加一个Toggle Group,将空对象移入每个Toogle的Inspector>Toogle>Group中,运行即可实现单选,Toggle Group的Allow Switch Off指允许取消勾选,即选择后可以实现一个都不选。
7.4滑动条Slider的使用
示例
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
Slider slider;
void Start()
{
slider = transform.Find("Slider").GetComponent<Slider>();
slider.onValueChanged.AddListener(OnValueChanged);
}
void OnValueChanged(float value)
{
Debug.Log("进度条的值为:"+slider.value);
}
}
该段代码的功能是,在控制台显示slider滑动的值。
7.5滚动视图与遮罩的使用
7.5.1滚动视图Scroll View
滚动视图是容纳多个图标的容器,可以通过拖动滚动条来查看所有的图标,因为在Scroll View中的Viewport含有Mask组件,所以,图标只会在滚动视图内显示。
7.5.2Mask和Rect Mask 2D
Mask作为父物体的组件时,子物体超出父物体的部分不会显示,这里会识别父物体的透明度,透明度高的部分也不会被显示。
Rect Mask 2D作为父物体的组件时功能与Mask相同,但不会识别父物体的透明度,父物体以矩形方式呈现。
7.6水平、垂直、网格布局组件与布局元素
7.6.1水平、垂直和网格布局
水平布局组件:Horizontal Layout Group,在Scroll View>View Port>Content中加入该组件,可以将滚动视图中的图像设置成一行,并进行相关设置。
垂直布局组件:Vertical Layout Group,在Scroll View>View Port>Content中加入该组件,可以将滚动视图中的图像设置成一列,并进行相关设置。
网格布局组件:Grid Layout Group,在Scroll View>View Port>Content中加入该组件,可以将滚动视图中的图像设置成方固定方格排列,并进行相关设置。
7.6.2布局元素
布局元素组件:Layout Element,网格布局元素中的单个图像若添加该组件,并选择组件中的Ignore Layout,可以使该图像自由移动,不受网格限制。
7.7内容尺寸适配器Context Size Fitter
7.7.1内容尺寸适配器
该组件英文名Context Size Fitter,当在内容输入文本框或者在Scroll View>View Port>Content的网格状态下使用该组件,把Horizontal Fit项设置成Preferred Size时,可以根据内容自适应左右宽度的大小,Vertical Fit同理。
7.7.2克隆元素图标
示例
using UnityEngine;
public class Clone : MonoBehaviour
{
public GameObject hero;
public Transform content;
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
GameObject clonehero=GameObject.Instantiate(hero);
clonehero.transform.parent = content;
}
}
}
将元素图标的预制件与HeroPanel>Scroll View>View Port>Content拖入该脚本并将该脚本挂到penel中后,可以在播放时通过按A键来克隆物体。
7.8UI特效与图片填充功能
7.8.1UI特效
Outline组件,该组件可以通过设置大小、颜色等给UI元素(如图片)描边。
Shadow组件,该组件可以通过设置大小、颜色等给UI元素(如图片)设置阴影。
7.8.2图片型进度条制作
示例
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class FullFill : MonoBehaviour
{
public Image image;
void Start()
{
StartCoroutine(Fill());
}
IEnumerator Fill() //协程就是要等时间
{
float value = 0;
while(value<=1)
{
yield return new WaitForSeconds(0.5f);
value+=0.1f;
image.fillAmount = value;
}
}
}
新建两个层级不同的Image,父Image设置成背景色,子Image设置成填充色,并在子Image的Sourse Image中导入一张图片,将Image Type设置成Filled,将Fill Method设置成Horizontal,将Fill Origin设置成Left,将含上面代码的脚本挂到某一物体上,将子Image挂到脚本中,可以实现实现播放时的进度条加载效果。
8.用户输入管理
8.1虚拟轴
使用的API:.GetAxis("/*Edit>Project Settings>Input Manager>Axes中对应的名字*/");
8.1.1控制位置
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
if (horizontal != 0)
{
transform.position=new Vector3(transform.position.x+horizontal*0.1f, transform.position.y,transform.position.z);
}
if(vertical != 0)
{
transform.position=new Vector3(transform.position.x,transform.position.y+vertical*0.1f,transform.position.z);
}
}
}
该段代码实现的目标是在运行时可以通过WASD来控制前后左右,Horizontal和Vertical是Edit>Project Settings>Input Manager>Axes中Horizontal和Vertical的名字。
8.1.2控制旋转
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
if (horizontal != 0)
{
transform.eulerAngles=new Vector3(transform.eulerAngles.x, transform.eulerAngles.y+horizontal, transform.eulerAngles.z);
}
}
}
该段代码实现的功能是通过AD来控制左右旋转。
8.1.3控制其他
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
Debug.Log(Input.GetAxis("Mouse X"));
}
}
该段代码实现的功能是在控制台输出鼠标在X轴方向移动的值,Mouse X也可以换成Edit>Project Settings>Input Manager>Axes中的其他值来实现相应的控制。
8.2获取键盘事件
使用的API:GetKey("相应的键"/*也可以用KeyCode.A*/)
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
if (Input.GetKey("a"/*也可以用KeyCode.A*/))
{
Debug.Log("A键被按下了");
}
}
}
该段代码实现的功能是,在按住A键时控制台不停输出:A键被按下了。
若上面代码将GetKey换成GetKeyDown,则控制台会在按键按下时打印一次输出。
若上面代码将GetKey换成GetKeyUp,则控制台会在按键抬起时打印一次输出。
8.3获取鼠标事件
8.3.1获取鼠标按键
使用的API:GetMouseButtonDown(数字)、GetMouseButtonUp(数字)、GetMouseButton(数字)/*数字0代表鼠标左键,数字1代表鼠标右键,数字2代表鼠标滚轮*/
示例1
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonDown(0))
{
GameObject cube = GameObject.Find("Cube");
cube.transform.localScale=new Vector3(2,2,2);
}
}
}
画面中创建一个立方体,当上述代码执行时,按下鼠标左键,画面中的立方体会放大一倍。
若将上面代码中的GetMouseButtonDown换成GetMouseButtonUp则会在按键抬起时执行效果。
示例2
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonDown(0))
{
GameObject cube = GameObject.Find("Cube");
cube.transform.localScale+=new Vector3(1,1,1);
}
}
}
上述代码的功能是,在播放时不停按下鼠标左键,立方体会被不断放大。
8.3.2获取鼠标位置
使用的API:Input.mousePosition;
示例
using UnityEngine;
public class Test : MonoBehaviour
{
bool isDown=false;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
isDown=true;
}
if (Input.GetMouseButtonUp(0))
{
isDown = false;
}
if (isDown)
{
GameObject go = GameObject.Find("Image");
go.transform.position=Input.mousePosition;
}
}
}
创建一个图片,该段代码实现的功能是,点击鼠标左键后,图片会回到鼠标指针所在的位置,当鼠标持续点击并移动时,图片会跟随鼠标指针。
8.4移动设备输入
使用的API:Input.touchCount
Input.touches[0].fingerId
Input.touches[0].position
Input.touches[0].deltaPosition;
示例
using UnityEngine;
using UnityEngine.UI;
public class MyText : MonoBehaviour
{
Text juse;
void Start()
{
juse = GameObject.Find("Text").GetComponent<Text>();
}
void Update()
{
if (Input.touchCount >= 1)
{
juse.text= "当前有:" + Input.touchCount + "根手指触碰。" + "当前手指的ID是:" + Input.touches[0].fingerId + "当前手指所在位置是:" + Input.touches[0].position + "从上一帧到现在移动了:" + Input.touches[0].deltaPosition;
}
}
}
在场景中新建一个Text,将上面的代码写好并打包成apk文件,运行apk文件,在点击屏幕的时候,屏幕上会显示当前有几根手指触碰,当前手指的ID,当前手指所在位置,和从上一帧到现在移动了多少。
9.自然环境设计
9.1天空盒的创建
9.1.1六张图片创建
在Project中新建材质,将Inspector>Shader中将材质设置成Skybox>6 Side,导入6张照片,将6张照片添加进Inspector中,再将新建材质拖入Scene中。
9.1.2全景图片创建
在Project中新建材质,将Inspector>Shador中将材质设置成Skybox>Cubemap,导入一张全景图片,将图片的Texture Shape设置成Cube,再将图片拖进新建材质的Inspector中,将新建材质拖入Scene中。
9.2山脉和地表贴图的创建
在Hierachy视图中新建Terrain物体,在Terrain的Inspector>Terrain中对地形进行修改,如果要Paint Texture需要先创建图层。
9.3树和草的创建
通过在Terrain的Inspector>Terrain中对地形添加树和草,树和草均需要先添加图层。
在Hierachy中添加Windzone来使树木在播放时有风吹效果。
9.4水和雾
通过将一个水的预制件(也可自己制作,即一个有动态纹理的平面)加入场景实现水的效果。
通过点击Lighting>Other Seeting>Fog来实现雾的效果,还可在下面设置雾的颜色,密度等。
10.光照系统
10.1灯光组件
10.1.1区域灯光的使用
先将Lighting>Mixed Lighting>Baked Global Illumin选项打开,并将Lighting>Lightmap Setting>Lightmapper设置为progressive GPU(preview),,创建一个区域光和一个其他类型(直线光、点光、和聚光都可)的光源,设置区域光的光照范围和颜色,在Lighting中点击Generate Lighting就可以看到静态的物体被渲染成了区域光的颜色,而其非静态物体则不受影响,烘焙后的物体的颜色将一直保存,不随区域光的删除而消失,除非在Lighting中点击Generate Lighting重新生成照明。
10.1.2灯光组件介绍
灯光组件的添加及灯光组建的功能。
10.2照明设置
照明设置打开方式:Windows>Rendering>Lighting Setting.
介绍了Lighting的一些按钮功能。
10.3自发光
自发光物体创建方式:在Project中新建材质,在新建材质的组件中将Emission勾选上,将挂上贴图和设置颜色,在将新建材质挂到物体的Mesh Render>Material中,即可以实现物体的自发光。
10.4光照探测器
自发光可以在Generate Lighting后让静态物体有烘焙效果,但对非静态物体无效。
通过在Hierachy里添加光照探测器,并编辑光照探测器的范围,让非静态物体在光照探测器的范围之内,点击Lighting>Generate Lighting,可以使非静态物体也能有烘焙效果。
10.5反射探测器
若一个房间里的地板上反射的灯光模糊,可以在Hierachy里添加反射探测器,将反射探测器调整至合适的大小,将房间的地板在组件中取消勾选Matellic,并将Smooth的值拉到最大,将反射探测器组件中的Type改为Realtime,此时地面就可以呈现镜子般反射灯光的效果。
12.3D物理系统
12.1刚体组件介绍
介绍了刚体组件Rigidbody的中一些选项的功能。
Rigidbody组件中的Is Kinematic勾选上后,该物体将不会受到碰撞等效果的影响。
12.2刚体常用的方法
12.2.1Constant Forse组件
可以在该组件中设置不同方向的恒定力,Relative表示按照相对坐标的的方向确定力。
12.2.2添加刚体速度
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
rb.velocity = new Vector3(0, 0, 5);
}
}
该段代码的功能是,使脚本所挂的物体在世界坐标的Z轴方向以5的速度运动。
12.2.3添加力
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
rb.AddForce (new Vector3(0, 0, 10f));
}
}
该段代码的功能是在代码所挂的物体上添加一个世界坐标Z轴方向的大小为50的力。
若想添加相对坐标的Z轴的方向的力,可以将上述代码中的rb.AddForce(new Vector3(0, 0, 10f));改为rb.AddRelativeForce (new Vector3(0, 0, 10f));
若想添加世界坐标Z轴方向的扭矩力,可以将上述代码中的rb.AddForce(new Vector3(0, 0, 10f));改为rb.AddTorque (new Vector3(0, 0, 10f));
若想添加相对坐标Z轴方向的扭矩力,可以将上述代码中的rb.AddForce(new Vector3(0, 0, 10f));改为rb.AddRelativeTorque (new Vector3(0, 0, 10f));
ForceMode 力的模式
在unity中,Rigidbody.AddForce()实现对刚体物体施加力的效果,实现物体例如碰撞,爆炸等等效果
调用函数如下:
public void AddForce(Vector3 force, ForceMode mode = ForceMode.Force);
public void AddForce(float x, float y, float z, ForceMode mode = ForceMode.Force);
AddForce()函数有一个参数 ForceMode , 为枚举类型
Force:添加一个可持续力到刚体,使用它的质量
Acceleration:添加一个可持续加速度到刚体,忽略它的质量。
Impulse:添加一个瞬间冲击力到刚体 ,使用它的质量。( 爆炸或碰撞力量 )
VelocityChange:添加一个瞬间速度变化给刚体,忽略它的质量。
具体介绍如下:
在以下举例中均设刚体质量为m=2.0f,力向量为f=(10.0f,0.0f,0.0f)。
1 . ForceMode.Force:默认方式,使用刚体的质量计算,时间间隔以系统帧频间隔计算(默认值为0.02s)。
则由动量定理 f • t = m • v
可得:10 * 0.02 = 2.0 * v1,从而可得 v1=0.1 m/s,即每秒刚体在X轴上值增加0.1米
2 . ForceMode.Acceleration:忽略刚体的实际质量而采用默认值m = 1.0f,时间间隔以系统帧频间隔计算(默认值为0.02s)
则 f • t = 1.0 • v
可得:10 * 0.02 = 1.0 * v2,从而可得 v2=0.2 m/s,即每秒刚体在X轴上值增加0.2米
3 . ForceMode.Impulse:采用瞬间力作用方式,即默认 t = 1.0f,不再采用系统的帧频间隔
则 f • 1.0 = m • v
可得:10 * 1.0 = 2.0 * v3,从而可得 v3=5.0 m/s,即每秒刚体在X轴上值增加5.0米
4 . ForceMode.VelocityChange:忽略刚体的实际质量,采用默认值m = 1.0f,同时也忽略系统的实际帧频间隔,采用默认间隔 t = 1.0f
则 f • 1.0 = 1.0 • v
可得:10 * 1.0 = 1.0 * v4,从而可得 v4=10.0 m/s,即每秒刚体在X轴上值增加10.0米
12.2.4爆炸力
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetKeyDown("a"))
{
rb.AddExplosionForce(500f, transform.position, 10f);/*三个参数分别是:爆炸力度、爆炸位置、爆炸范围*/
}
}
}
该段代码的功能是在运行时按下A键后,组件所挂的物体在原位置受到一个大小为500f的力。
12.2.5刚体的唤醒和休眠
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetKeyDown("a"))
{
rb.Sleep();
}
else if (Input.GetKeyDown("b"))
{
rb.WakeUp();
}
}
}
该段代码实现的功能是,在运行状态下按A键,刚体组件将失效,再按B键刚体组件将恢复效果。
12.3碰撞器和触发器
12.3.1碰撞器组件介绍
1.点了碰撞器组件中的Is Trigger按钮后,碰撞器变为触发器。
2.触发和碰撞检测的条件
碰撞器条件:1.碰撞与被碰撞物体都需要有碰撞器组件且都不能勾选为触发器。2.挂脚本的物体上有刚体组件。
触发器条件:1.碰撞与被碰撞物体,至少有一个勾选为触发器。2挂脚本的物体上有刚体组件。
12.3.2碰撞器
示例
using UnityEngine;
public class Test : MonoBehaviour
{
private void OnCollisionEnter(Collision collision)
{
Debug.Log("I had collision");
}
}
该段代码的功能是,脚本所挂物体发生碰撞时控制台打印:我发生了碰撞。
若想在结束碰撞时调用控制台打印,可以将上述代码中的private void OnCollisionEnter(Collision collision)换成private void OnCollisionExit(Collision collision)。
若想在碰撞停留时调用控制台打印,可以将上述代码中的private void OnCollisionEnter(Collision collision)换成private void OnCollisionStay(Collision collision)。
12.3.3触发器
示例
using UnityEngine;
public class Test : MonoBehaviour
{
private void OnTriggerEnter(Collider collider)
{
Debug.Log("I had Trigger.");
}
}
该段代码的功能是,脚本所挂物体发生碰撞时控制台打印:我发生了触发。
若想在结束触发时调用控制台打印,可以将上述代码中的private void OnTriggerEnter(Collider collider)改为private void OnTriggerExit(Collider collider)。
若想在触发停留时调用控制台打印,可以将上述代码中的private void OnTriggerEnter(Collider collider)改为private void OnTriggerStay(Collider collider)。
12.3.4所碰撞物体
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public void OnCollisionEnter(Collision collision)
{
Debug.Log("Collision object is:" + collision.gameObject.name);
}
}
该段代码可以在运行时打印脚本所挂物体所碰撞的物体名称。
12.4力的常用函数
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Rigidbody rb;
void Start()
{
rb = transform.GetComponent<Rigidbody>();
Vector3 direction = transform.position + new Vector3(0, 1, 0) - transform.position;
rb.AddForceAtPosition(direction * 10f, transform.position);
}
}
该函数的功能是,使脚本所挂物体受到一个指定方向和作用点的力。
12.5物理材质
物理材质在Project>Creat>Physics Material中创建,创建后可以设置摩檫力、弹力等值,设置后拖入物体的Collider组件中,便可使组件具有该物理性质。
注意,当两个碰撞的物体设置了不同的结合方式时,采用的顺序如下: Average < Minimum < Multiply < Maximum,例如一个设置Minimum,一个设置Maximum,那么结合方式为Maximum。
12.6关节组件
12.6.1组件效果
固定关节组件(Fixed Joint):想两个物体用棍子连载一起。
弹簧关节组件(Spring Joint):像两个物体用弹簧连在一起。
铰链关节组件(Hinge Joint):像两个物体用铰链连在一起。
角色关节组件(Character Joint):可以模拟角色的骨骼关节。
可配置关节组件(Configurable Joint):可模拟任意关节效果。
12.6.2关节力度检测
检测断开的代码,脚本API:OnJointBreak
示例
using UnityEngine;
public class Test : MonoBehaviour
{
private void OnJointBreak(float force)
{
Debug.Log("Joint is break,force is:" + force);
}
}
该段代码的功能是在设置了关节断开的力度后,运行时断开会在控制台打印关节断开了,并显示断开时的力度。
12.7射线
12.7.1射线的绘制
第一种方式:
脚本API:Debug.DrawLine(起点位置,终点位置,颜色,持续时长,是否被遮挡);
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Debug.DrawLine(transform.position, new Vector3(5, 5, 5), Color.blue, 10,true);
}
}
上述脚本的功能是,在脚本所挂物体处发射一条终点坐标为(5,5,5)的,蓝色的,延迟10秒的,可被遮挡的射线。
第二种方式:
脚本API:Debug.DrawRay(起点位置,方向和长度,颜色,持续时长,是否被遮挡);
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Debug.DrawRay(transform.position,new Vector3(0,1,0),Color.blue,10,true);
}
}
上述脚本的功能是,在脚本所挂物体处发射一条朝(0,1,0)方向的,两点之间长度的,蓝色的,延迟10秒的,可被遮挡的射线。
12.7.2射线检测
1.检测单个物体
第一种方式
using UnityEngine;
public class Test : MonoBehaviour
{
Ray ray;
RaycastHit hit;
void Update()
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
Debug.Log("Mouse point attached to " + hit.transform.name);
}
}
}
将含上面代码的脚本挂到摄像机上,在运行时可以显示鼠标指向的物体的名称。
第二种方式
使用的API:Physics.Raycast(射线,光线碰到的物体out hit(类型RaycastHit),射线长度float,遮罩过滤层LayerMask)
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Camera camera;
void Start()
{
camera = GameObject.Find("Main Camera").GetComponent<Camera>();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = camera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100f))
{
Debug.Log("Hitted,Position is:" + hit.point + ",Object name is:" + hit.collider.gameObject.name);
}
else
{
Debug.Log("No hitted");
}
}
}
}
该段代码的功能是,在运行并用鼠标左键点击某处后如果发生了碰撞,控制台打印发生了碰撞,并打印碰撞的位置和碰撞的物体名称。
第三种方式
使用的API:Physics.Raycast(射线起点Vector3,射线方向Vector3,光线碰到的物体out hit(类型RaycastHit),射线长度float,遮罩过滤层LayerMask)
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public LayerMask layerMask;
void Start()
{
layerMask = LayerMask.GetMask("Boss");
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, 100f, layerMask))
{
Destroy(hit.collider.gameObject);
}
else
{
Debug.Log("miss hitted target");
}
}
}
}
创建两个物体,该两个物体的X,Y轴数值相同,将含上面代码的脚本挂到两个物体中Z轴数值小的物体上,在Inspector中将两个物体的Layer设置成“Boss”,在两个物体的中间加一个物体将两个物体隔开,将该物体的Layer设置成另一种,运行后点击鼠标左键,Z轴数值大的物体将被销毁。
2.检测多个物体
碰到的物体形成数组
用到的API:Physics.RaycastAll(射线,射线最大长度fioat,遮罩过滤层LayerMask)
也可以用:Physics.RaycastAll(射线起点Vector3,射线方向Vector3,射线长度float,遮罩过滤层LayerMask)
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit[] hit=Physics.RaycastAll(transform.position,transform.forward,100f);
for(int i = 0; i < hit.Length; i++)
{
Debug.Log("Hitted "+hit.Length+" object");
Debug.Log("No." + i + " name is " + hit[i].collider.gameObject.name);
}
}
}
}
该段代码的功能是将探测的物体组成一个数组,并通过控制台访问数组的信息。
3.球形射线
使用的API:Physics.OverlapSphere(transform.position,3f);
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Collider[] colliders = Physics.OverlapSphere(transform.position, 3f);
for(int i = 0; i < colliders.Length; i++)
{
Debug.Log("Hitted " + colliders.Length + " objects");
Debug.Log("No. " + i + " name is " + colliders[i].gameObject.name);
}
}
}
该段代码的功能是,检测一个球形内的碰撞体信息,并用控制台输出。
13.2D物理系统
13.1 2D的物理碰撞和触发器
13.1.1碰撞和触发的条件
碰撞的条件:两个物体都要带有碰撞器,其中一个需要有刚体。
触发的条件:碰撞的两个物体至少有一个勾选了Is Trigger选项。
13.1.2碰撞的生命周期
使用的脚本API:OnCollisionEnter2D
示例
using UnityEngine;
public class Player : MonoBehaviour
{
private void OnCollisionEnter2D(Collision2D collision)
{
Debug.Log("I collided "+collision.gameObject.name);
}
}
该段代码的功能是,在两个2D物体发生碰撞时,控制台打印进入碰撞和脚本所挂物体碰到的物体名称。
若想在碰撞结束时打印,可以将上述代码中的OnCollisionEnter2D改为OnCollisionExit2D。
若想在碰撞发生时打印,可以将上述代码中的OnCollisionEnter2D改为OnCollisionStay2D。
13.1.3触发的生命周期
使用的脚本API:OnTriggerEnter2D
示例
using UnityEngine;
public class Player : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D collision)
{
Debug.Log("I trigged " + collision.gameObject.name);
}
}
该段代码的功能是,在两个2D物体发生接触时,控制台打印进入接触和脚本所挂物体接触到的物体名称。
若想在接触结束时打印,可以将上述代码中的OnTriggerEnter2D改为OnTriggerExit2D。
若想在接触持续时打印,可以将上述代码中的OnTriggerEnter2D改为OnTriggerStay2D。
13.2 2D物理材质
讲了Project中新建的Physice Material 2D的使用。
13.3 2D效果器
讲了2D效果器组件,包括:
1.Area Effector 2D
2.Surface Effector 2D
3.Buoyancy Effector 2D
4.Point Effector 2D
13.4 2D物体中的其他碰撞器与恒力组件
讲了Capsule Collider 2D,Circle Collider 2D,Edge Collider 2D组件。
讲了Constant Force 2D组件。
13.5 脚本与2D刚体的交互
示例
using UnityEngine;
public class Player : MonoBehaviour
{
Rigidbody2D r2;
void Start()
{
r2 = transform.GetComponent<Rigidbody2D>();
}
void Update()
{
float x = Input.GetAxis("Horizontal");
float y = Input.GetAxis("Vertical");
if (x != 0 || y != 0)
{
r2.velocity = new Vector2(100 * x, 100 * y);
}
}
}
该段代码实现的功能是,通过WSAD来控制对象的上下左右移动。
14.动画系统
14.1动画的播放控制
14.1.1通过组件控制
导入模型后,在Project中新建一个Animator Controller,双击Animator Controller,将模型内部的动画文件拖入到Animator Controller的场景中,再将Animator Controller拖入到模型的Animator组件(如果没有该组件可以新创建一个)的Controller中,再点击运行模型即可动起来。
14.1.2通过脚本控制
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Animator am;
void Start()
{
am = transform.GetComponent<Animator>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha0))
{
am.SetInteger("id", 0);
}
else if (Input.GetKeyDown(KeyCode.Alpha1))
{
am.SetInteger("id", 1);
}
else if (Input.GetKeyDown(KeyCode.Alpha2))
{
am.SetInteger("id", 2);
}
else if (Input.GetKeyDown(KeyCode.Alpha3))
{
am.SetInteger("id", 3);
}
else if (Input.GetKeyDown(KeyCode.Alpha4))
{
am.SetInteger("id", 4);
}
}
}
在Prooject中创建一个Animator Controller,将动画拖进Animator Controller中,在Animator中设置通过Any State设置动画的播放,在Parameter中设置一个名叫id的变量,点击Animater中的箭头,在Inspector中设置动漫所对应的值,并将Inspector>Setting>Can Transition To Self取消勾选,通过该代码可以实现在运行时,通过按设置的值实现相应的动画效果。
14.2人形动画
人形动画的特点是可以使用其他的人形动画。
14.3动画遮罩
动画遮罩的功能是屏蔽游戏对象某一部位的运动。
14.4动画的分层和退出控制
动画的分层控制是在Animator中添加多个Layer,并对各个Layer进行编辑,来对物体的动作进行分类控制。
14.5动画事件
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public void TestDebug()
{
Debug.Log("Test event");
}
}
可以在Project的动画文件的Inspector>Animatian>Events中添加动画事件,通过将脚本中的函数名(本例为TestDebug)粘贴至中Inspector>Animatian>Events>Founction中,运行后在动画播放到设置的位置时会激活函数。
15.寻路系统
15.1实现简单导航寻路功能
示例
using UnityEngine;
using UnityEngine.AI;
public class Test : MonoBehaviour
{
private NavMeshAgent agent;
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
bool iscollider = Physics.Raycast(ray, out hit);
if (iscollider)
{
agent.SetDestination(hit.point);
}
}
}
}
将地面物体的Inspector设置成Navigation Static.然后点击菜单Windows>AI>Navigation,将地面物体进行Bake.在待引导的物体上添加Nav Mesh Agent组件。将上述代码挂到待引导物体上,在运行时可以实现通过鼠标左键控制物体运动。
15.2导航面板参数介绍以及导航网格区域介绍
可以在Navigation>Areas中为不同区域添加不同的行走成本,再在Navigation>Object中设置道路成本类型,通过设置成本可以是物体智能的选择走哪条路。
15.3动态障碍物
将Nav Mesh Obstacle组件挂到一个阻碍物体上,并选中该组件中的Carve后,可以使待引导物体检测到阻碍物体而重新规划路线。
15.4分离导航连接线
在地面添加Off Mash Link组件,可以在该组件中设置两个点,设置好后待引导物体可以在这两个点之间移动。
15.5运动时动态烘培导航网格
需要用到Unity官方扩展的Navigation工具。
添加扩展工具后,可以添加NavMeshSurface组件,该组件生成导航网格不需要将地面物体设置成Navigation Static,并可以通过脚本动态生成物体并烘焙。
15.6其他组件功能介绍
Unity官方扩展的Navigation工具中的NavMashLink,该组件为OffMash Link的加强版,可以连接两个导航面。
16.音效系统
16.1音频源和音频监听器组件
音频播放可以选择在Hierachy中单独创建Audio Source物体,也可以选择在物体的Inspector中添加Audio Source组件来播放音频。
需要有Audio Listener组件方可听到播放的音频。
16.2音频源组件常用的函数
16.2.1常用功能
使用的API:
播放音频:AudioSours.Play();
暂停播放:AudioSours.Pause();
停止播放:AudioSours.Stop();
检测是否在播放:AudioSourse.isPlaying
示例
using UnityEngine;
public class Test : MonoBehaviour
{
AudioSource audio;
void Start()
{
audio = transform.GetComponent<AudioSource>();
}
void Update()
{
if (Input.GetKeyDown("a"))
{
if (audio.isPlaying == false)
{
audio.Play();
}
else
{
Debug.Log("Audio is playing,no need to play again.");
}
}
if (Input.GetKeyDown("b"))
{
audio.Pause();
}
if (Input.GetKeyDown("c"))
{
audio.Stop();
}
}
}
将该脚本挂入Audio Sourse物体后,可以实现按A键播放(如果已经在播放,则打印在播放),按B键暂停播放,按C键停止播放。
16.2.2指定音频剪辑
使用的API:AudioSource.clip
示例
using UnityEngine;
public class Test : MonoBehaviour
{
AudioSource audio;
void Start()
{
audio = transform.GetComponent<AudioSource>();
audio.clip = Resources.Load<AudioClip>("kuaidi1");
}
void Update()
{
if (Input.GetKeyDown("a"))
{
audio.Play();
}
}
}
该段代码的功能是,将Resources中的kuaidi1音频文件添加进组件,在游戏播放时按A键可以播放音频。
16.3音频过滤器和音频混响区
16.3.1音频过滤器
音频过滤器组件需要在有Audio Sources组件或Audio Listener组件的物体中才能添加。
16.3.2音频混响区
音频混响区组件Audio Reverb Zone,该组件可以设置在一定区域内的混响效果。
16.3.3音频管理器
打开方式:Edit>Project Setting>Audio.
11.3D模型管理
11.1蒙皮网格与普通网格对比
11.1.1对比
共同点:二者都可以通过关闭网格组件来隐藏物体
不同点:蒙皮网格适用于野怪等动画人物,普通网格适用于树等静态物,且普通网格有网格过滤器(Mesh filter),蒙皮网格没有。
11.1.2通过脚本控制网格组件的开关
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public void Start()
{
transform.GetComponent<MeshRenderer>().enabled = false;
}
}
在将脚本挂到对应的物体后,上述脚本实现的功能是在运行时将网格组件关闭使该物体不再显示,如果为动态物体,可以将上面的代码transform.GetComponent<MeshRenderer>().enabled= false;换成transform.GetComponent<SkinnedMeshRenderer>().enabled= false;
11.2材质的使用
新建或导入物体模型后,在Project中新建一个Material,将新建的Material导入到物体模型的Inspector>Mash Rander>Materials>Elements中,然后通过在新建的Marerial的Inspector中对材质进行Main Map>Albedo中导入图片,变换颜色等设置来改变物体材质。
11.2换肤功能的实现
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public MeshRenderer cube;
public Material material1;
public Material material2;
void Update()
{
if (Input.GetKeyDown("a"))
{
cube.material = material1;
}
if (Input.GetKeyDown("b"))
{
cube.material = material2;
}
}
}
将含上面代码的脚本挂到目标物体身上,并将目标物体拖入到脚本的MeshRenderer选项中,再将2套需要变换的材质分别拖入到脚本的material1和material2选项中,点击运行,按A键和按B键后可以实现皮肤的变换。
17.特效系统
17.1粒子系统
演示了一些粒子系统的效果。
创建粒子系统,Hierachy中点击右键Effect>Particle System.
17.2使用脚本和粒子系统交互
17.2.1基本交互
示例
using UnityEngine;
public class Test : MonoBehaviour
{
GameObject particleGO;
ParticleSystem particle;
void Start()
{
particleGO = GameObject.Instantiate(Resources.Load<GameObject>("22_RFX_Fire_Campfire1"));
particleGO.transform.position = transform.position;
particle = particleGO.GetComponent<ParticleSystem>();
ParticleSystem.MainModule mainModule = particle.main;
mainModule.loop = true;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
particle.Play();
}
if (Input.GetKeyDown(KeyCode.B))
{
particle.Stop();
}
if (Input.GetKeyDown(KeyCode.C))
{
particle.Pause();
}
if (Input.GetKeyDown(KeyCode.D))
{
Destroy(particleGO);
}
}
}
新建一个空物体,将含上面代码的脚本挂在空物体上,将名为22_RFX_Fire_Campfire的粒子特效预制体放入Projece/Resources文件夹中,可以实现在运行时将粒子特效预制体22_RFX_Fire_Campfire克隆并在点击A键时播放,B键时停止,C键时暂停,D键时销毁。
17.2.2碰撞回调
使用的API:OnParticleCollision(GameObject go)
示例
using UnityEngine;
public class Test : MonoBehaviour
{
private void OnParticleCollision(GameObject go)
{
Debug.Log("Particle had collision,collide to:" + go.name);
}
}
将该段代码挂到粒子系统物体的主子物体上,并将该主物体Inspector>Particle System>Collision勾选上,把Collision>Type设置成World,Collision>Mode设置成3D,Collision>Send Collision Messages勾选上,在粒子上方放一物体,运行时控制台会打印粒子发生了碰撞和碰撞到的物体名称。
17.3粒子触发回调
示例
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
ParticleSystem particle;
void Start()
{
particle = transform.GetComponent<ParticleSystem>();
}
private void OnParticleTrigger()
{
List<ParticleSystem.Particle> particles = new List<ParticleSystem.Particle>();
int numEnter = particle.GetTriggerParticles(ParticleSystemTriggerEventType.Enter, particles);
for (int i = 0; i < numEnter; i++)
{
ParticleSystem.Particle pt = particles[i];
pt.startColor = Color.red;
particles[i] = pt;
}
particle.SetTriggerParticles(ParticleSystemTriggerEventType.Enter, particles);
}
}
在粒子系统上方放一个物体,将该物体拖入粒子系统的Inspector>Particle System>Triggers>Colliders中,将Inspector>Particle System>Triggers>Enter设置成Callback,将含上面代码的脚本挂载到粒子系统物体上,运行时可以使粒子进入物体后变成红色。
17.4特效系统之拖尾
使用的API:TrailRenderer
示例
using UnityEngine;
public class Test : MonoBehaviour
{
GameObject go;
void Start()
{
go = GameObject.Instantiate(Resources.Load<GameObject>("Accelerate"));
go.transform.SetParent(transform);
go.transform.localPosition = new Vector3(0, 0.5f, 0);
}
void Update()
{
if (Input.GetKeyDown("a"))
{
go.GetComponent<TrailRenderer>().emitting = true;
}
if (Input.GetKeyDown("b"))
{
Destroy(go);
}
}
}
新建一个物体,将含上面代码的脚本挂载到该物体上,准备一个拖尾的预制体Accelerate放入Resources文件夹中,在运行时按下A键可以激活克隆的Accelerate,使拖动时表现出效果,按下B键时销毁克隆的Accelerate。
17.5特效系统之粒子力场
讲了Hierachy中点击右键Effect>Particle System Force Field的相关知识点。
18.视频播放管理
18.1视频播放方法
在场景中新建RawImage,在RawImage中添加Video Player组件,在Assets中新建Render Texture,将Render Texture和视频资源分别放入Raw Image和Video Player组件中,点击即可播放。
18.2视频组件常用的函数
18.2.1视频播放常用操作
示例
using UnityEngine;
using UnityEngine.Video;
public class Test : MonoBehaviour
{
VideoPlayer video;
void Start()
{
video = transform.GetComponent<VideoPlayer>();
}
void Update()
{
if (Input.GetKeyDown("a"))
{
if (video.isPlaying == false)
{
video.Play();
}
else
{
Debug.Log("Video is playing,no need to play again");
}
}
if (Input.GetKeyDown("b"))
{
video.Pause();
}
if (Input.GetKeyDown("c"))
{
video.Stop();
}
}
}
将该段代码挂到有Video Player组件的物体中,在运行时可以通过按键实现播放,暂停,停止等
18.2.2视频播放组件设置
示例
using UnityEngine;
using UnityEngine.Video;
public class Test : MonoBehaviour
{
VideoPlayer video;
void Start()
{
video = transform.GetComponent<VideoPlayer>();
video.source = VideoSource.VideoClip;
video.clip = Resources.Load<VideoClip>("GameExplain");
}
}
将视频剪辑文件GameExplain放入Resources文件夹,将组件Video Player>Source设置成URL,通过该段代码可以实现在运行时Video Player>Source切换至Video Clip模式,并播放素材名为GameExplain的视频。
19.DoTween补间动画插件
19.1空间物体位置旋转大小等动画
19.1.1位置
使用的API:DOMove(位置,时间)
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOMove(new Vector3(10, 10, 10), 2f);
}
}
当前代码的功能是将脚本所挂物体用2秒移动到世界坐标系(10,10,10)位置。
如果想以本地坐标系作为参考,可以将上面代码中的transform.DOMove(new Vector3(10,10,10), 2f);换成transform.DOLocalMove(new Vector3(10,10,10), 2f);
如果想将物体沿X轴移动,可以将上面代码中的transform.DOMove(new Vector3(10,10,10), 2f);换成transform.DOLocalMoveX(10, 2f);
如果想让物体匀速运动,需要将transform.DOMove(new Vector3(10, 10, 10), 2f);改为transform.DOMove(new Vector3(10, 10, 10), 2f).SetEase(Ease.Linear);
19.1.2旋转
使用的API:DORotate(角度,时间)
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DORotate(new Vector3(0, 20, 0), 2f);
}
}
当前代码的功能是将脚本所挂物体用2秒沿世界坐标系的Y轴顺时针转20度。
如果想以本地坐标系为参考旋转,可以将上面代码中的transform.DORotate(new Vector3(0, 20, 0), 2f);改为transform.DOLocalRotate(new Vector3(0, 20, 0), 2f);
19.1.3缩放
使用的API:DOScale(缩放倍数,时间)
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOScale(new Vector3(6, 6, 6), 2f);
}
}
该段代码的功能是,将脚本所挂物体的X,Y,Z轴三个方向都缩放至6倍.
如果只想让X轴方向缩放至6,可以将上面代码中的transform.DOScale(new Vector3(6, 6, 6), 2f);换成transform.DOScaleX (6, 2f);
19.1.4跳跃
使用的API:DOJump(跳跃目的地位置,跳跃高度,步数,时间)
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOJump(new Vector3(60, 0, 0), 1,5,6);
}
}
该段代码的功能是,使脚本所挂物体在6秒内以Y轴方向1高度分5步跳到指定位置。
如果想以当地坐标系为参考,可以将上面代码中的transform.DOJump(new Vector3(60,0,0),1,5,6);换成transform.DOLocalJump(new Vector3(60,0,0),1,5,6);
19.1.5弹簧冲击
使用的API:DOPunchPosition(位置, 时间, 频率, 对侧弹性);
DOPunchRotation(new Vector3(角度,时间, 频率, 对侧弹性);
transform.DOPunchScale(缩放倍数, 时间, 频率, 对侧弹性);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOPunchPosition(new Vector3(10, 0, 0), 3,10,1);
}
}
该段代码实现的功能是,使脚本所挂物体用3秒,每秒10次,以最大的弹性的来回弹跳。
如果想实现物体的角度弹簧冲击,可以将上面代码中的transform.DOPunchPosition(new Vector3(10, 0, 0), 3, 10, 1);换成transform.DOPunchRotation(new Vector3(10, 0, 0), 3, 10, 1);
如果想实现物体缩放的弹簧冲击,可以将上面代码中的transform.DOPunchPosition(new Vector3(10, 0, 0), 3, 10, 1);换成transform.DOPunchScale(new Vector3(10, 0, 0), 3, 10, 1);
19.1.6旋转
使用的API:.DOLookAt(旋转的方向,时间);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOLookAt(new Vector3(1,1,1), 2f);
}
}
该段代码实现的功能是用2秒沿着指定方向自旋转。
19.1.7增量
使用的API:DOBlendableMoveBy(位置增量, 时间);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOBlendableMoveBy(new Vector3(20,0,0), 2f);
}
}
该段代码的功能是,是脚本所挂物体用2秒在X轴方向的坐标增加20。
如果想实现旋转角度的增量,可以将上面代码transform.DOBlendableMoveBy(new Vector3(20, 0, 0), 2f);换成transform.DOBlendableRotateBy(new Vector3(20, 0, 0), 2f);
如果想实现缩放的增量,可以将上面代码transform.DOBlendableMoveBy(new Vector3(20, 0, 0), 2f);换成transform.DOBlendableScaleBy(new Vector3(20, 0, 0), 2f);
19.2颜色、透明度的控制
19.2.1颜色
使用的API:DOColor(颜色,时间);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Material material = GetComponent<MeshRenderer>().material;
material.DOColor(Color.red, 2f);
}
}
该段代码的功能是用两2秒将脚本所挂物体变成红色。
该方法也可用于文本和图片颜色的更改。
19.2.2透明度
使用的API:DOFade(透明度,,时间);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Material material = GetComponent<MeshRenderer>().material;
material.DOFade(0, 2f);
}
}
将脚本所挂物体的Inspector>Shader修改成Lagacy Shader>TransParent>Diffuse,通过上面的代码可以用2秒将脚本所挂物体隐形。
19.2.3颜色渐变
使用的API:
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
public Gradient gradient;
void Start()
{
Material material = GetComponent<MeshRenderer>().material;
material.DOGradientColor(gradient, 2f);
}
}
定义了公开变量gradient后,在Unity中Inspector中找到gradient并设置该渐变色,设置完成后运行,该段代码功能是使脚本所挂物体的颜色用2秒渐变。
19.3震动效果表现
19.3.1物体震动
使用的API:DOShakePosition(时间, 振幅,频率,混乱程度);
transform.DOShakeRotation(时间, 角幅度,频率,混乱程度);
transform.DOShakeScale(时间, 大小幅度,频率,混乱程度);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOShakePosition(2f, 1, 10, 90);
}
}
该段代码实现的功能是,使脚本所挂物体用2秒以1振幅,10振幅,90混乱度的状态震动。
如果想换成方向震动,可以将上述代码中的transform.DOShakePosition(2f, 1, 10, 90);换成transform.DOShakeRotation(2f, 90, 10, 90);
如果想换成大小震动,可以将上述代码中的transform.DOShakePosition(2f, 1, 10, 90);换成transform.DOShakeScale(2f,2, 10, 90);
19.3.2摄像机震动
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOShakePosition(2f, 1, 10, 90);
}
}
定义了摄像机后,将指定摄像机拖入该变量中,通过该段代码可以实现摄像机的震动。
参考上一小节,同理可实现摄像机的角震动。
19.4物体路径动画
使用的API:DOPath(路径,时间,路径类型,路径模式,分辨率,颜色);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Vector3[] path = new Vector3[] { new Vector3(1, 2, 1), new Vector3(2, 1, 3), new Vector3(10, 2, 5), new Vector3(4, 9, 6) };
transform.DOPath(path, 5,PathType.Linear,PathMode.Full3D,10,Color.red);
}
}
该段代码的功能是,使脚本所挂物体以设置的模式沿路径运动
除了用脚本控制物体运动外,还可以通过Dotween Path组件来控制物体的运动。
19.5动画序列Sequence
19.5.1动画序列
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Sequence sequence = DOTween.Sequence();
sequence.Append(transform.DOMoveX(10,1));
sequence.Insert(0,transform.DOScale(2,1));
sequence.AppendInterval(2);
sequence.Append(transform.DOMoveX(0,1));
sequence.Insert(3,transform.DOScale(1,1));
}
}
该段代码实现的功能是,用1秒钟使被挂脚本的物体在X轴移动到10的位置,同时大小变为原来的2倍,停顿两秒后,物体X轴的位置变为0,同时大小变回原来的大小。
上面代码中Insert方法也可以用Join方法来实现同样的功能,只需将代码sequence.Insert(0, transform.DOScale(2, 1));换成sequence.Join(transform.DOScale(2, 1));并将sequence.Insert(3,transform.DOScale(1, 1));换成sequence.Join(transform.DOScale(1, 1));即可。
19.5.2方法回调
Append回调:
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Sequence sequence = DOTween.Sequence();
sequence.Append(transform.DOMoveX(10,1));
sequence.Join(transform.DOScale(2,1));
sequence.AppendCallback(() =>
{
Debug.Log("AppendCallback1");
});
sequence.Append(transform.DOMoveX(0,1));
sequence.Join(transform.DOScale(1,1));
sequence.AppendCallback(() =>
{
Debug.Log("AppendCallback2");
});
}
}
AppendCallback会在上面的代码执行完后调用。
Insert回调:
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Sequence sequence = DOTween.Sequence();
sequence.Append(transform.DOMoveX(10,1));
sequence.Insert(0,transform.DOScale(2,1));
sequence.AppendInterval(2);
sequence.Append(transform.DOMoveX(0,1));
sequence.Insert(3,transform.DOScale(1,1));
sequence.InsertCallback(6,() =>
{
Debug.Log("InsertCallback2");
});
}
}
该段代码会在运行6秒后打印InsertCallback,即InsertCallback的执行时间点只与填写的时间点有关。
19.6动画常用设置以及动画控制
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
Tweener tweener;
void Start()
{
tweener=transform.DOMoveX(10,1).SetEase(Ease.Linear).SetLoops(-1,LoopType.Restart).SetDelay(0).SetAutoKill(true);
}
private void onGUI()
{
if (GUILayout.Button("暂停"))
{
tweener.Pause();
}
if (GUILayout.Button("Kill"))
{
tweener.Kill();
}
if (GUILayout.Button("播放"))
{
tweener.Play();
}
if (GUILayout.Button("倒回播放"))
{
tweener.PlayBackwards();
}
if (GUILayout.Button("向前播放"))
{
tweener.PlayForward();
}
if (GUILayout.Button("重新播放"))
{
tweener.Restart();
}
if (GUILayout.Button("回到初始位置"))
{
tweener.Rewind();
}
if (GUILayout.Button("跳转到"))
{
tweener.Goto(2);
}
if (GUILayout.Button("点击暂停"))
{
tweener.TogglePause();
}
}
}
该段代码的功能是,设置一段动画,并通过不同的按键来控制动画。(运行问题:游戏页面无法形成控制按钮)
21.各平台打包操作
21.1Windows平台
讲解了Windows平台的打包操作
21.2安卓平台
安卓平台的打包需要先在Hub中安装Android SDK & NDK Tools和Open JDK两个组件。
21.3IOS平台
讲解了IOS平台的打包操作
19.7动画的回调
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
Tweener tweener;
void Start()
{
tweener=transform.DOMoveX(10,1).SetEase(Ease.Linear).SetLoops(-1,LoopType.Restart).SetDelay(0).SetAutoKill(true);
tweener.OnComplete(() =>
{
Debug.Log("OnComplete");
});
tweener.OnKill(() =>
{
Debug.Log("OnKill");
});
tweener.OnPlay(() =>
{
Debug.Log("OnPlay");
});
tweener.OnStart(() =>
{
Debug.Log("OnStart");
});
tweener.OnRewind(() =>
{
Debug.Log("OnRewind");
});
tweener.OnUpdate(() =>
{
Debug.Log("OnUpdate");
});
tweener.OnPause(() =>
{
Debug.Log("OnPause");
});
}
}
该段代码的功能是根据动画运行时的不同状态打印相应的提示。
20.EasyTouch手势插件
20.1手势监测之初级使用
示例
using HedgehogTeam.EasyTouch;
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
Gesture gesture = EasyTouch.current;
if (gesture != null)
{
if (EasyTouch.EvtType.On_TouchStart == gesture.type)
{
OnTouchStart(gesture);
}
else if (EasyTouch.EvtType.On_Drag == gesture.type)
{
OnDragStart(gesture);
}
}
}
private void OnTouchStart(Gesture gesture)
{
Debug.Log(gesture.type);
}
private void OnDragStart(Gesture gesture)
{
Debug.Log(gesture.type);
}
}
上述代码的功能是,当运行时鼠标点击或者拖拽被挂脚本物体,控制台打印相关信息。
20.2手势监测之使用QuickGesture以及Trigger
20.2.1QuickGesture类组件
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public void Log(string str)
{
Debug.Log(str);
}
}
新建一个空物体,讲脚本挂入空物体中,然后将空物体挂入待操作物体的Quick Drag,Quick Tap,Quick Touch,Quick Pinch等组件中,设置相关输出内容,在运行时进行对物体进行操作后,会输出相关内容。
20.2.2Trigger组件
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public void Log(int str)
{
Debug.Log(str);
}
}
将含该代码的脚本挂入待操作物体上,并在待操作物体上加入Trigger组件,选择Add new event>On_Touch Start,将Mothed name改成Log,将Parameter to send改为Touch_Count,在运行时将对物体的操作信息通过控制台打印。
20.3组件核心参数
讲解了Easy Touch组件
20.4JoyStick虚拟摇杆
讲解了ETCJoystick组件
22.各平台调试技术
22.1常见的异常
22.1.1空指针导致的异常
空指针异常可以分为未指定引用对象(包括未指定和未分配对象),和指定的路径错误(包括查找物体和查找资源)两类。
22.1.2数据结构错误
包括重复添加相同的Key和索引出现异常。
22.2编辑器模式下的日志功能
日志的三种类型:
普通日志:Debug.Log("普通日志");
警告日志:Debug.LogWarning("警告日志");
错误日志:Debug.LogError("错误日志");
22.3安卓平台下的日志跟踪
分为Unity本身的调试和AndroidStudio调试。
22.4IOS调试日志查看
讲解了IOS平台下的日志查看。
22.5断点调试和调用堆栈
22.5.1断点调试
在一些代码前面加入断点,点击附加到Unity,在Unity中点击播放,返回Visual Studio中查看相关代码的值。
22.5.2调用堆栈
在Visual Studio中操作
23.其他知识
23.1生成随机数
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
for(int i = 0; i < 10; i++)
{
Debug.Log(Random.Range(0,8));
}
}
}
该段代码的功能是在运行时控制台随机打印10个0~7之间的随机数。
23.2协程方法
示例1
using System.Collections;
using UnityEngine;
public class Test : MonoBehaviour
{
private void Start()
{
StartCoroutine(MyCoroutine(2, "success"));
}
IEnumerator MyCoroutine(int i, string str)
{
Debug.Log(i);
yield return new WaitForSeconds(5f);
Debug.Log(str); // 打印i的5s后执行
yield return new WaitForSeconds(5f);
Debug.Log("123"); // 打印str的5s后执行
}
}
该段代码的功能是间隔一定时间打印内容。
示例2
using System.Collections;
using UnityEngine;
public class Test : MonoBehaviour
{
private void Start()
{
StartCoroutine(MyCoroutine(2));
}
IEnumerator MyCoroutine(int i)
{
while (true)
{
yield return new WaitForSeconds(1);
Debug.Log(i);
}
}
}
该段代码的作用是每过1秒打印一次数字2.
23.3调用方法
示例1
using UnityEngine;
public class Test : MonoBehaviour
{
private void Start()
{
Invoke("Bigger",2);
}
void Bigger()
{
transform.localScale = new Vector3(2, 2, 2);
}
}
该代码的作用是使脚本所挂物体在2秒后变为原来的2倍。
示例2
using UnityEngine;
public class Test : MonoBehaviour
{
private void Start()
{
InvokeRepeating("Bigger",2,1);
}
void Bigger()
{
transform.localScale += new Vector3(1, 1, 1);
}
}
该代码的作用是使脚本所挂物体2秒后增大1倍,然后每1秒增大1倍。
示例3
using UnityEngine;
public class Test : MonoBehaviour
{
private void Start()
{
InvokeRepeating("Fuse", 0.01f,0.01f);
}
private void Fuse()
{
transform.Translate(new Vector3(0.02f, 0.02f, 0.02f));
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
CancelInvoke();
}
}
}
该段代码的功能是,使物体持续朝一个方向运动,在按下鼠标左键后停止运动。
23.3触发器
示例
using UnityEngine;
public class zidan : MonoBehaviour
{
void OntriggerEnter(Collider coll)
{
if (coll.name == "Cube")
{
//transform.position 生成一个特效到这个位置上
Destroy(transform.gameObject);
}
else if (coll.name == "xiaonuhai")
{
//transform.position 生成一个别的特效到这个位置上
Destroy(transform.gameObject);//打中小女孩后,销毁子弹
Destroy(coll.gameObject);//打中小女孩后,销毁小女孩
}
}
}
23.5按键控制程序退出
示例
using UnityEngine;
using UnityEngine.UI;
public class Exit : MonoBehaviour
{
void Start()
{
transform.GetComponent<Button>().onClick.AddListener(() => { DoExit(); });
}
void DoExit()
{
UnityEditor.EditorApplication.isPlaying= false;
Application.Quit();
}
}
上述代码的功能是,当按键被按下时,退出游戏。
23.6Text中显示时间
示例
using System;
using UnityEngine;
using UnityEngine.UI;
public class ShowTime : MonoBehaviour
{
public Text time1;
void Update()
{
DateTime nowTime=DateTime.Now.ToLocalTime();
time1.text = nowTime.ToString("yyyy-MM-dd HH:mm:ss");
}
}
上述代码可以实现在Text中显示实时时间。
23.7Text字体隐形显现转换
示例
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
public class FlashWord : MonoBehaviour
{
private void Start()
{
Pingpong(1, 0, 0.6f);
}
void Pingpong(float fromValue, float toValue, float duration)
{
Color temColor = gameObject.GetComponent<Text>().color;
temColor.a = fromValue;
Tweener tweener = DOTween.ToAlpha(() => temColor, x => temColor = x, toValue, duration);
tweener.onUpdate = () => { gameObject.GetComponent<Text>().color = temColor; };
tweener.onComplete = () =>
{
Pingpong(toValue, fromValue, duration);
};
}
}
上述代码可以实现将字体的显隐变换效果,将<Text>改为<Image>可以实现图片的显隐效果。
23.8关闭程序
示例
using UnityEngine;
using UnityEngine.UI;
public class Exit : MonoBehaviour
{
void Start()
{
transform.GetComponent<Button>().onClick.AddListener(() => { DoExit(); });
}
void DoExit()
{
// UnityEditor.EditorApplication.isPlaying= false;
Application.Quit();
}
}
上述代码可以实现点击按键关闭程序。“//”后的代码加上后可以实现在编辑器模式下的关闭效果,但加上后无法打包成安卓应用。
23.9实现UI圆点跟随运动
示例
using System.Collections;
using DG.Tweening;
using UnityEngine;
public class AfterScanDotsMove : MonoBehaviour
{
public Transform[] Dots;
Vector3[] tempvec3;
void Start()
{
tempvec3 = new Vector3[Dots.Length];
StartCoroutine(DotsMove());
}
IEnumerator DotsMove()
{
while (true)
{
for (int i = 0; i < Dots.Length; i++)
{
tempvec3[i] = Dots[i].position;
}
for (int i = 0; i < Dots.Length; i++)
{
if (i < Dots.Length - 1)
{
Dots[i].transform.DOMove(tempvec3[i + 1], 0.5f).SetEase(Ease.Linear);
}
else
{
Dots[i].transform.DOMove(tempvec3[0], 0.5f).SetEase(Ease.Linear);
}
}
yield return new WaitForSeconds(0.5f);
}
}
}
该代码可以实现小圆点的跟随运动。
23.10全局变量
//该脚本不用挂载,内数据不会随场景变化而变化
public class storeData
{
public static int countData = 0;
}
//其他脚本可以使用这个数据
if (storeData.countData ==0)
23.11单例(一个脚本调另一个脚本里的变量或方法)
示例
//待调用的代码
using UnityEngine;
public class Juse : MonoBehaviour
{
public static Juse m_Instance;
void Start()
{
m_Instance = this;
}
public void OpenPage()
{
//待调用的方法
}
}
//调用的代码
using UnityEngine;
public class TimeShow : MonoBehaviour
{
void Start()
{
Juse.m_Instance.OpenPage();
}
}
23.12SendMessenger方法调用
示例
//待调用的脚本代码
using UnityEngine;
public class TakeMess : MonoBehaviour
{
public void DebugWord(string str)
{
Debug.Log(str);
}
}
//调用的脚本代码
using UnityEngine;
public class SendMess : MonoBehaviour
{
void Start()
{
GameObject.Find("Cube").SendMessage("DebugWord", "juse");
}
}
该代码可以调用Cube物体上的DebugWord方法,并传递相关参数。
若想调用自身及子物体上的方法,可以用BroadcastMessage( );
若想调用自身及父物体上的方法,可以用SendMessageUpwards( );
23.13List使用
List也叫列表,
23.14Dictionary使用
Dictionary也叫字典。
23.15Event Trigger组件
通过Event Trigger组件来控制鼠标的事件
23.16UI小窗口显示
再UI界面建一个Row Image,Hierarchy上新建一个摄像机,Project上新建一个Render Texture,将Render Texture分别挂在摄像机和Row Image上,就可以在Row Image上显示摄像机摄的东西。
23.17AssetBundle
1.打包
将要打包的资源在inspector中的预览窗口下设置要打包在AssetBundles下的路径和后缀名(可任意取)。新建一个C#脚本,脚本内容如下:
using System.IO;
using UnityEditor;
public class CreateAssetBundles
{
[MenuItem("Assets/Build AssetBundles")]//生成菜单目录
static void BuildAllAssetBundles()
{
string assetBundleDirectory = "Assets/AssetBundles";//指定AssetBundles文件夹的目录
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);//如果没有,则创建文件夹
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows);
}
}
脚本无需挂载,在菜单Assets下点击新创建的Build AssetBundles,即可在指定文件夹创建AssetBundle.
2.读取
场景中物体上挂载一个脚本,脚本代码如下:
using UnityEngine;
public class LoadAssetBundle : MonoBehaviour
{
void Start()
{
AssetBundle bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/this/wall.ab");//找到AB包
GameObject cubeWall = bundle.LoadAsset<GameObject>("CubeWall");//找到AB包中的物体
Instantiate(cubeWall);//实例化物体
}
}
Unity
1.基本介绍
1.1Unity的安装与汉化_引擎安装与基础操作
安装时先安装Unity Hub,再安装Unity.
汉化在Unity Hub的Installs中找到对应版本的Unity,左上角的设置按钮,在跳出的窗口选择中文包,下载安装好后进入Unity,在Edit>Preferences>Languages>Editor Languages中选择中文版本。
1.2Unity窗口界面介绍与布局
2.2.1Scene界面
1.鼠标右键旋转视角
2.按住鼠标滚轮移动视角
3.旋转鼠标滚轮调整远近视角
4.按住右键并按WASD可以在场景中进行漫游
5.Pivot和Center
Pivot表示轴心,在该状态下,点击父物体时坐标会落在父物体上,旋转时也是子物体围绕父物体旋转。
Center表示中心,在该状态下,点击父物体时坐标会落在父物体与其所有的子类物体(包括孙物体和后面的物体)的中心点,旋转时也会围绕该中心点旋转。
6.Global和Local
Global表示全局,在该状态下,旋转后物体的坐标方向会与原始的坐标方向一致。
Local表示局部,在该状态下,旋转后物体的坐标会保持旋转后的方向。
2.2.2Project界面
选择文件并右键点击Show in explorer可以打开所在文件夹
1.3Unity菜单
Fils,Edit,Assets,...等菜单的功能。
2.游戏流程控制与脚本基础
2.1脚本生命周期
2.1.1方法名
示例
using UnityEngine;
public class Test : MonoBehaviour
{
/*游戏开始时调用,在脚本组件未勾选的情况下也可运行。*/
void Awake()
{
Debug.Log("Awake");
}
/*当物体被启用时调用*/
void OnEnable()
{
Debug.Log("Enable");
}
/*没有Reset方法的情况下,会在执行OnEnable方法后执行*/
void Start()
{
Debug.Log("Start");
}
/*每帧调用一次,一般用于非物理运动,例如游戏的逻辑。*/
int updateCount = 0;
void Update()
{
Debug.Log("Update第" + UpdateCount++ + "次打印");
}
/*以相同的时间间隔调用,用在力学更新效果中。*/
int fixedUpdateCount = 0;
void FixedUpdate()
{
Debug.Log("FixedUpdate第" + FixedUpdateCount++ + "次打印");
}
/*在Update和FixedUpdate调用后调用。*/
int lateUpdateCount = 0;
void LateUpdate()
{
Debug.Log("LateUpdate第" + LateUpdateCount++ + "次打印");
}
/*当物体被禁用时调用*/
void OnDisable()
{
Debug.Log("OnDisable");
}
/*当物体销毁后执行*/
void OnDestroy()
{
Debug.Log("Ondestroy");
}
}
该段代码的功能是,通过控制台打印观察方法的执行顺序
2.1.2检测调用间隔时间
使用的API:Time.deltaTime;
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
Debug.Log("Update"+Time.deltaTime);
}
}
该脚本实现的功能是每帧输出一次文字Update和每帧的间隔时间。
2.2变量的创建与使用
2.2.1变量的创建
变量在类下面直接创建,默认为私有,如为私有可省略Private.
2.2.1变量的操作
1.隐藏Publicb变量
在变量上方用 [HideInInspector]
示例
using UnityEngine;
public class Test : MonoBehaviour
{
[HideInInspector] //序列化 隐藏
public int num;
}
2.显示private变量
在变量上方用[SerializeField]
示例
using UnityEngine;
public class Test : MonoBehaviour
{
[SerializeField] //序列化 显示
private int num;
}
3.设置变量范围
在变量上方用[Range(a,b)]
示例
using UnityEngine;
public class Test : MonoBehaviour
{
[Range(1, 100)]
public int num;
}
3.游戏素材与脚本
3.1游戏素材
游戏素材包括字体,图片,音频,视频,模型,场景,粒子特效等。
素材的添加可以通过在Project中点击右键选择Import New Assets或Import Package实现,也可以通过文件夹拖入的方式实现。
3.2游戏脚本
游戏脚本可以通过在Project中点击右键Create>C# Script创建。
游戏脚本需要挂载到物体上方能实现其功能。
游戏脚本命名不能加空格,否则无法挂载。
4.游戏物体
4.2物体的标签和层级
标签可以方便查找物体。
层级可以运用在一些操作上,比如Camera中Inspector中的Culling Mask上,可以通过勾选掉一些层级来屏蔽显示一些物体
4.3摄像机
组件Camera>Projection下的persepective表示透视,透视模式下可以通过Field in view调镜头的角度;另一个Orthography表示正交即在播放时场景没有透视效果。
组件Camera>Clipping Planes为视距设置选项,在视距范围之外(高于最远视距,低于最近视距)的物体无法被摄像机看到。
4.4预制件
4.4.1克隆预制件
使用的API:GameObject.Instantiate(变量名);
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = Resources.Load<GameObject>("Cubes/Cube");
GameObject.Instantiate(go);
}
}
在Project中新建Resources文件夹,在Resources文件夹下新建Cubes文件夹,将Hierachy中做好的物体Cube拖入Cubes文件夹中,制成预制件。该段代码实现的功能是:在运行时将Resources/Cubes文件夹中的Cube预制件克隆一份并显示。
4.4.2修改预制件
预制件的修改的两种方式;
第一种:在Project中双击预制件,或者在Hietachy中点击其中一个预制件的最后的“>”标志,进入预制件修改视图,在修改视图中进行预制件的修改。
第二种:在Hierachy中选择一个预制件,直接进行修改,修改后再单击Hierachy中的预制件,在Inspector中找到Override按钮,点击按钮并选择Apply All即可完成对预制体的修改。预制件的Inspector中的组件参数修改后会留下标记,在标记行点击鼠标右键会出现Apply to prefab”/*预制件名称*/”的提示框,点击即将修改应用至预制件。
4.5通过脚本操作物体
4.5.1查找物体
1.按照路径查找物体
使用的API:GameObject.Find(物体的Hietachy路径);
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
go.SetActive(false);
}
}
在Hierachy中新建一个物体Cube,在Cube下新建一个子物体Sphere,将含上面代码的脚本挂载到某一物体上,可以实现在运行时隐藏物体Sphere,若一个文件夹下有同名的多个物体,则查找到的物体为创建时间最短的物体。
2.按照标签查找
使用的API:GameObject.FindGameObjectWithTag("标签名");
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.FindGameObjectWithTag("Player");
go.SetActive(false);
}
}
该段代码的功能是找到最后将标签设置成Player的物体,并在运行时隐藏该物体。
4.5.2修改物体名称
使用的API:物体名.name=”修改后物体名称”;
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
go.name = "CuteSphere";
}
}
该段代码功能是找到物体Sphere,并在运行时将该物体名称改为CuteSphere。
4.5.3修改物体位置
使用的API:变量名.transform.position=/*更改后的位置*/
示例:
using UnityEngine;
public class Temp : MonoBehaviour
{
public GameObject cube;
void Start()
{
cube.transform.position = new Vector3(2, 1, 3);
}
}
该段代码功能是,将物体的位置移动到世界坐标(2,1,3)的位置。
如果是想让物体移动到相对坐标(2, 1, 3)的位置,可将代码cube.transform.position = new Vector3(2, 1, 3);写成cube.transform.localposition = new Vector3(2, 1, 3);
如果想让找到的物体在运行时旋转一定角度,可以将上面示例中的代码cube.transform.position = new Vector3(2, 1, 3);写成go.transform.Rotation= Quaternion.Euler(new Vector3(a, b, c))或cube.transform.eulerAngles = new Vector(a,b,c))/*a,b,c表示旋转角度*/;
如果想让找到的物体在运行时放大或缩小,可以将上面示例中的代码cube.transform.position = new Vector3(2, 1, 3);写成cube.transform.localScale = new Vector3(a,b,c))/*a,b,c表示放大倍数*/;
4.5.4删除物体
使用的API:Destroy( );
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
Destroy(go);
}
}
该段代码功能是找到物体Sphere,并在运行时删除该物体。
如果想实现在运行后5秒消除,可以将代码Destroy(go);修改为Destroy(go,5);。
如果想让物体在切换场景的时候不销毁,可以将Destroy(go);修改为DontDestroyOnLoad(go);。
4.5.5克隆物体
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
public GameObject Cube;
void Start()
{
GameObject.Instantiate(Cube);
}
}
将含上面代码的脚本挂载到某一物体上,并将需要克隆的物体Cube拖入脚本组件中,运行后便可在场景中得到一个克隆的预制体Cube。
5.物体组件
5.1组件的基本操作
代码类名后面跟的MonoBehaviour使脚本能够挂到物体的组件中。
组件在Inspector视图中,可以通过最下面的Add Component添加组件,通过组件点击组件名左边的勾选符号打开或关闭组件,通过组件名右边的三个点下面的Remove Component移除组件。
5.2通过脚本操作组件
5.2.1添加组件
使用的API:AddComponent</*组件名称*/>();
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
go.AddComponent<Rigidbody>();
}
}
该段代码先找出物体Sphere,运行时在该物体上添加Rigidbody组件。
5.2.2查找组件
1.查找单个组件
使用的API:GetComponent</*组件名称*/>()
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
go.GetComponent<SphereCollider>().radius = 1;
}
}
该段代码的功能是,先查找Sphere物体,然后查找Sphere物体的SphereCollider组件,并将该组件中radios值改为1。
如果想查找该物体及其子物体的某个组件,可以将示例代码中的go.GetComponent<SphereCollider>().radius = 1;改为go.GetComponentInChildren<SphereCollider>().radius = 1;,改完之后会查找该物体及其子物体的该组件类型,找到一个后便停止,不再继续查找。
如果想查找该物体及其父物体的某个组件,可以将示例代码中的go.GetComponent<SphereCollider>().radius = 1;改为go.GetComponentInParent<SphereCollider>().radius = 1;改完之后会查找该物体及其父物体的该组件类型,找到一个后便停止,不再继续查找。
2.查找多个同类型的组件
使用的API:GetComponents<AudioSource>();
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
SphereCollider[] sphereColliders= go.GetComponents<SphereCollider>();
Debug.Log("查找到多少个:"+sphereColliders.Length);
}
}
这段代码的功能是,先找到Sphere物体,找出物体里所有SphereCollider组件,将找到的组件放入数组SphereCollider中,并通过控制台打印数组的长度。
如果想查找该物体及其子物体的某个组件,可以将示例代码中的SphereCollider[] sphereColliders= go.GetComponents<SphereCollider>();改为SphereCollider[] sphereColliders= go.GetComponentsInChildren<SphereCollider>();改完之后会查找该物体及其子物体的所有该组件类型。
如果想查找该物体及其父物体的某个组件,可以将示例代码中的SphereCollider[] sphereColliders= go.GetComponents<SphereCollider>();改为SphereCollider[] sphereColliders = go.GetComponentsInParent<SphereCollider>();改完之后会查找该物体及其父物体的所有该组件类型。
5.2.3删除组件
使用的API:Destroy(/*要删除的组件类型*/);
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
SphereCollider sphereCollider = go.GetComponent<SphereCollider>();
Destroy(sphereCollider);
}
}
该段代码的功能是,找到物体Sphere,并在运行时删除该物体的SphereCollider组件。SphereCollider sphereCollider = go.GetComponent<SphereCollider>();改为Component sphereCollider = go.GetComponent<SphereCollider>();也可实现该效果。
5.2.4关闭和激活组件
使用的API:enabled=false;
示例:
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
GameObject go = GameObject.Find("Cube/Sphere");
go.GetComponent<SphereCollider>().enabled=false;
}
}
该代码的功能是,找到物体Sphere,并在运行时关闭该物体的SphereCollider组件。
如果想要激活组件,可以将上面示例中的go.GetComponent<SphereCollider>().enabled=false;改为go.GetComponent<SphereCollider>().enabled=true;
6.场景管理
6.1场景的基础操作
6.1.1场景的创建
场景创建的快捷键Ctrl+N可以快捷创建场景,此时创建的场景为临时场景,需要保存起来后续才能使用。
6.1.2场景的删除
直接在文件夹中进行删除即可,因为场景中可能会有一些依赖项,因此非必要不要删除场景。
6.2同步加载场景
6.2.1切换场景
使用的API:SceneManager.LoadScene( );
示例:
using UnityEngine;
using UnityEngine.SceneManagement;
public class Test : MonoBehaviour
{
void Start()
{
SceneManager.LoadScene("Scenes/SampleScene1");
}
}
先将两个场景导入File>Build Settings...中,将含上面代码的脚本挂到待切换场景的一个物体上,该脚本可以实现将场景切换至Scenes文件夹下的SampleScene1场景播放;
地址"Scenes/SampleScene1"也可换成该场景在Build Settings...中所对应的序号。
6.2.2同时加载场景
使用的API:SceneManager.LoadScene( ,LoadSceneMode.Additive);
示例:
using UnityEngine;
using UnityEngine.SceneManagement;
public class Test : MonoBehaviour
{
void Start()
{
SceneManager.LoadScene("Scenes/SampleScene1",LoadSceneMode.Additive);
}
}
先将两个场景导入File>Build Settings...中,将含上面代码的脚本挂到原场景的一个物体上,该脚本可以实现将原将原场景与Scenes文件夹下的SampleScene1场景同时加载;
地址"Scenes/SampleScene1"也可换成该场景在Build Settings...中所对应的序号。
6.3异步加载场景
示例
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Test : MonoBehaviour
{
void Start()
{
StartCoroutine(Load());
}
private IEnumerator Load()
{
AsyncOperation asyncOperation=SceneManager.LoadSceneAsync("Scene/Cut");
asyncOperation.allowSceneActivation = false;
while (asyncOperation.progress < 0.9f)
{
Debug.Log("Current progress is " + asyncOperation.progress);
yield return null;
}
asyncOperation.allowSceneActivation = true;
if (asyncOperation.isDone)
{
Debug.Log("Finished load and skip.");
}
else
{
Debug.Log("Not finished");
}
}
}
不理解该段代码
6.4加载场景时保留物体
使用的API:DontDestroyOnLoad( );
示例:
using UnityEngine;
using UnityEngine.SceneManagement;
public class Test : MonoBehaviour
{
void Start()
{
GameObject capsule = GameObject.Find("Capsule");
DontDestroyOnLoad(capsule);
SceneManager.LoadScene("Scenes/SampleScene1");
}
}
先将两个场景导入File>Build Settings...中,将含上面代码的脚本挂到原场景的一个物体上,该脚本实现的功能是将原场景切换至Scenes文件夹下的SampleScene1场景后保留原场景的Cube物体及该物体下面的子物体,该代码保留的物体只能是根物体,即没有父物体的物体。
地址"Scenes/SampleScene1"也可换成该场景在Build Settings...中所对应的序号。
7.UGUI图形系统
7.1画布与事件系统
7.1.1画布
画布用于承载所有的UI元素。
Canvas物体的Canvas组件Render Mode分为三种:
第一种:Screem Space Overlay模式,该模式下画布中的元素始终在前面。
第二种:Screem Space Camera模式,该模式下画布中的元素是否在前取决于它与物体的位置。
第三种:World Space模式,该模式下画布可以自由移动缩放。可用来做人物的血条等。
7.1.2事件系统
事件系统是使画布内元素产生效果系统,创建画布后会自动创建,如果不小心删除也可点击添加单独创建。
7.2图像、文本框、按钮、输入框的脚本交互
7.2.1登录按钮的脚本实现
示例
using UnityEngine;
using UnityEngine.UI;
public class Login : MonoBehaviour
{
InputField accountInput;
InputField passwordInput;
Button loginButton;
void Start()
{
accountInput = transform.Find("Account").GetComponent<InputField>();
passwordInput = transform.Find("Password").GetComponent<InputField>();
loginButton = transform.Find("Login").GetComponent<Button>();
loginButton.onClick.AddListener(LoginButtonOnClick);
}
void LoginButtonOnClick()
{
string account = accountInput.text;
string password = passwordInput.text;
Debug.Log("Account is " + account);
Debug.Log("Password is " + password);
}
}
该段代码实现的功能是,在输入账号和密码并点击登录键后,将账号和密码在控制台输出。
7.2.2更换背景图的脚本实现
示例
using UnityEngine;
using UnityEngine.UI;
public class Change : MonoBehaviour
{
public Sprite bg;
void Start()
{
transform.Find("Background").GetComponent<Image>().sprite = bg;
}
}
该段代码实现的功能是,在将新的图像添加到新建的脚本后,点击播放可以在运行时将背景图换成新的图像
7.2.3修改文本框
示例
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
string text = "抵制不良游戏,拒绝盗版游戏。注意自我保护,谨防受骗上当。\n适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。";
void Start()
{
transform.Find("Text").GetComponent<Text>().text = text;
}
}
该段代码实现的功能是,在运行时将文本框文字改为:抵制不良游戏,拒绝盗版游戏。注意自我保护,谨防受骗上当。适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。
7.2.4点击按钮导入链接
示例
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
void Start()
{
transform.Find("Button").GetComponent<Button>().onClick.AddListener(ButtonOnClick);
}
void ButtonOnClick()
{
Application.OpenURL("https://v.qq.com/channel/choice?channel_2022=1");
}
}
该段代码实现的功能是,在点击了Button按钮后,跳转到网站https://v.qq.com/channel/choice?channel_2022=1。
7.3切换开关与开关组
7.3.1切换开关
示例
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
InputField user;
InputField password;
Toggle toggle;
Button logon;
void Start()
{
user= transform.Find("User").GetComponent<InputField>();
password = transform.Find("Passward").GetComponent<InputField>();
toggle=transform.Find("Toggle").GetComponent<Toggle>();
logon=transform.Find("Logon").GetComponent<Button>();
logon.onClick.AddListener(logonOnClick);
}
void logonOnClick()
{
if (toggle.isOn == true)
{
string username= user.text;
string passwordnum=password.text;
Debug.Log("用户名是:"+username);
Debug.Log("密码是:"+passwordnum);
}
else
{
Debug.Log("请先同意用户协议");
}
}
}
该段代码实现的功能是,在点击了按钮后,可以正常登录,未点击时控制台显示:请先同意用户隐私协议!
7.3.2开关组
若有多个Toogle,而只能选择一个,可在Hierachy中新建一个空对象,在空对象的Inspector中添加一个Toggle Group,将空对象移入每个Toogle的Inspector>Toogle>Group中,运行即可实现单选,Toggle Group的Allow Switch Off指允许取消勾选,即选择后可以实现一个都不选。
7.4滑动条Slider的使用
示例
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
Slider slider;
void Start()
{
slider = transform.Find("Slider").GetComponent<Slider>();
slider.onValueChanged.AddListener(OnValueChanged);
}
void OnValueChanged(float value)
{
Debug.Log("进度条的值为:"+slider.value);
}
}
该段代码的功能是,在控制台显示slider滑动的值。
7.5滚动视图与遮罩的使用
7.5.1滚动视图Scroll View
滚动视图是容纳多个图标的容器,可以通过拖动滚动条来查看所有的图标,因为在Scroll View中的Viewport含有Mask组件,所以,图标只会在滚动视图内显示。
7.5.2Mask和Rect Mask 2D
Mask作为父物体的组件时,子物体超出父物体的部分不会显示,这里会识别父物体的透明度,透明度高的部分也不会被显示。
Rect Mask 2D作为父物体的组件时功能与Mask相同,但不会识别父物体的透明度,父物体以矩形方式呈现。
7.6水平、垂直、网格布局组件与布局元素
7.6.1水平、垂直和网格布局
水平布局组件:Horizontal Layout Group,在Scroll View>View Port>Content中加入该组件,可以将滚动视图中的图像设置成一行,并进行相关设置。
垂直布局组件:Vertical Layout Group,在Scroll View>View Port>Content中加入该组件,可以将滚动视图中的图像设置成一列,并进行相关设置。
网格布局组件:Grid Layout Group,在Scroll View>View Port>Content中加入该组件,可以将滚动视图中的图像设置成方固定方格排列,并进行相关设置。
7.6.2布局元素
布局元素组件:Layout Element,网格布局元素中的单个图像若添加该组件,并选择组件中的Ignore Layout,可以使该图像自由移动,不受网格限制。
7.7内容尺寸适配器Context Size Fitter
7.7.1内容尺寸适配器
该组件英文名Context Size Fitter,当在内容输入文本框或者在Scroll View>View Port>Content的网格状态下使用该组件,把Horizontal Fit项设置成Preferred Size时,可以根据内容自适应左右宽度的大小,Vertical Fit同理。
7.7.2克隆元素图标
示例
using UnityEngine;
public class Clone : MonoBehaviour
{
public GameObject hero;
public Transform content;
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
GameObject clonehero=GameObject.Instantiate(hero);
clonehero.transform.parent = content;
}
}
}
将元素图标的预制件与HeroPanel>Scroll View>View Port>Content拖入该脚本并将该脚本挂到penel中后,可以在播放时通过按A键来克隆物体。
7.8UI特效与图片填充功能
7.8.1UI特效
Outline组件,该组件可以通过设置大小、颜色等给UI元素(如图片)描边。
Shadow组件,该组件可以通过设置大小、颜色等给UI元素(如图片)设置阴影。
7.8.2图片型进度条制作
示例
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class FullFill : MonoBehaviour
{
public Image image;
void Start()
{
StartCoroutine(Fill());
}
IEnumerator Fill() //协程就是要等时间
{
float value = 0;
while(value<=1)
{
yield return new WaitForSeconds(0.5f);
value+=0.1f;
image.fillAmount = value;
}
}
}
新建两个层级不同的Image,父Image设置成背景色,子Image设置成填充色,并在子Image的Sourse Image中导入一张图片,将Image Type设置成Filled,将Fill Method设置成Horizontal,将Fill Origin设置成Left,将含上面代码的脚本挂到某一物体上,将子Image挂到脚本中,可以实现实现播放时的进度条加载效果。
8.用户输入管理
8.1虚拟轴
使用的API:.GetAxis("/*Edit>Project Settings>Input Manager>Axes中对应的名字*/");
8.1.1控制位置
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
if (horizontal != 0)
{
transform.position=new Vector3(transform.position.x+horizontal*0.1f, transform.position.y,transform.position.z);
}
if(vertical != 0)
{
transform.position=new Vector3(transform.position.x,transform.position.y+vertical*0.1f,transform.position.z);
}
}
}
该段代码实现的目标是在运行时可以通过WASD来控制前后左右,Horizontal和Vertical是Edit>Project Settings>Input Manager>Axes中Horizontal和Vertical的名字。
8.1.2控制旋转
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
if (horizontal != 0)
{
transform.eulerAngles=new Vector3(transform.eulerAngles.x, transform.eulerAngles.y+horizontal, transform.eulerAngles.z);
}
}
}
该段代码实现的功能是通过AD来控制左右旋转。
8.1.3控制其他
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
Debug.Log(Input.GetAxis("Mouse X"));
}
}
该段代码实现的功能是在控制台输出鼠标在X轴方向移动的值,Mouse X也可以换成Edit>Project Settings>Input Manager>Axes中的其他值来实现相应的控制。
8.2获取键盘事件
使用的API:GetKey("相应的键"/*也可以用KeyCode.A*/)
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
if (Input.GetKey("a"/*也可以用KeyCode.A*/))
{
Debug.Log("A键被按下了");
}
}
}
该段代码实现的功能是,在按住A键时控制台不停输出:A键被按下了。
若上面代码将GetKey换成GetKeyDown,则控制台会在按键按下时打印一次输出。
若上面代码将GetKey换成GetKeyUp,则控制台会在按键抬起时打印一次输出。
8.3获取鼠标事件
8.3.1获取鼠标按键
使用的API:GetMouseButtonDown(数字)、GetMouseButtonUp(数字)、GetMouseButton(数字)/*数字0代表鼠标左键,数字1代表鼠标右键,数字2代表鼠标滚轮*/
示例1
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonDown(0))
{
GameObject cube = GameObject.Find("Cube");
cube.transform.localScale=new Vector3(2,2,2);
}
}
}
画面中创建一个立方体,当上述代码执行时,按下鼠标左键,画面中的立方体会放大一倍。
若将上面代码中的GetMouseButtonDown换成GetMouseButtonUp则会在按键抬起时执行效果。
示例2
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonDown(0))
{
GameObject cube = GameObject.Find("Cube");
cube.transform.localScale+=new Vector3(1,1,1);
}
}
}
上述代码的功能是,在播放时不停按下鼠标左键,立方体会被不断放大。
8.3.2获取鼠标位置
使用的API:Input.mousePosition;
示例
using UnityEngine;
public class Test : MonoBehaviour
{
bool isDown=false;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
isDown=true;
}
if (Input.GetMouseButtonUp(0))
{
isDown = false;
}
if (isDown)
{
GameObject go = GameObject.Find("Image");
go.transform.position=Input.mousePosition;
}
}
}
创建一个图片,该段代码实现的功能是,点击鼠标左键后,图片会回到鼠标指针所在的位置,当鼠标持续点击并移动时,图片会跟随鼠标指针。
8.4移动设备输入
使用的API:Input.touchCount
Input.touches[0].fingerId
Input.touches[0].position
Input.touches[0].deltaPosition;
示例
using UnityEngine;
using UnityEngine.UI;
public class MyText : MonoBehaviour
{
Text juse;
void Start()
{
juse = GameObject.Find("Text").GetComponent<Text>();
}
void Update()
{
if (Input.touchCount >= 1)
{
juse.text= "当前有:" + Input.touchCount + "根手指触碰。" + "当前手指的ID是:" + Input.touches[0].fingerId + "当前手指所在位置是:" + Input.touches[0].position + "从上一帧到现在移动了:" + Input.touches[0].deltaPosition;
}
}
}
在场景中新建一个Text,将上面的代码写好并打包成apk文件,运行apk文件,在点击屏幕的时候,屏幕上会显示当前有几根手指触碰,当前手指的ID,当前手指所在位置,和从上一帧到现在移动了多少。
9.自然环境设计
9.1天空盒的创建
9.1.1六张图片创建
在Project中新建材质,将Inspector>Shader中将材质设置成Skybox>6 Side,导入6张照片,将6张照片添加进Inspector中,再将新建材质拖入Scene中。
9.1.2全景图片创建
在Project中新建材质,将Inspector>Shador中将材质设置成Skybox>Cubemap,导入一张全景图片,将图片的Texture Shape设置成Cube,再将图片拖进新建材质的Inspector中,将新建材质拖入Scene中。
9.2山脉和地表贴图的创建
在Hierachy视图中新建Terrain物体,在Terrain的Inspector>Terrain中对地形进行修改,如果要Paint Texture需要先创建图层。
9.3树和草的创建
通过在Terrain的Inspector>Terrain中对地形添加树和草,树和草均需要先添加图层。
在Hierachy中添加Windzone来使树木在播放时有风吹效果。
9.4水和雾
通过将一个水的预制件(也可自己制作,即一个有动态纹理的平面)加入场景实现水的效果。
通过点击Lighting>Other Seeting>Fog来实现雾的效果,还可在下面设置雾的颜色,密度等。
10.光照系统
10.1灯光组件
10.1.1区域灯光的使用
先将Lighting>Mixed Lighting>Baked Global Illumin选项打开,并将Lighting>Lightmap Setting>Lightmapper设置为progressive GPU(preview),,创建一个区域光和一个其他类型(直线光、点光、和聚光都可)的光源,设置区域光的光照范围和颜色,在Lighting中点击Generate Lighting就可以看到静态的物体被渲染成了区域光的颜色,而其非静态物体则不受影响,烘焙后的物体的颜色将一直保存,不随区域光的删除而消失,除非在Lighting中点击Generate Lighting重新生成照明。
10.1.2灯光组件介绍
灯光组件的添加及灯光组建的功能。
10.2照明设置
照明设置打开方式:Windows>Rendering>Lighting Setting.
介绍了Lighting的一些按钮功能。
10.3自发光
自发光物体创建方式:在Project中新建材质,在新建材质的组件中将Emission勾选上,将挂上贴图和设置颜色,在将新建材质挂到物体的Mesh Render>Material中,即可以实现物体的自发光。
10.4光照探测器
自发光可以在Generate Lighting后让静态物体有烘焙效果,但对非静态物体无效。
通过在Hierachy里添加光照探测器,并编辑光照探测器的范围,让非静态物体在光照探测器的范围之内,点击Lighting>Generate Lighting,可以使非静态物体也能有烘焙效果。
10.5反射探测器
若一个房间里的地板上反射的灯光模糊,可以在Hierachy里添加反射探测器,将反射探测器调整至合适的大小,将房间的地板在组件中取消勾选Matellic,并将Smooth的值拉到最大,将反射探测器组件中的Type改为Realtime,此时地面就可以呈现镜子般反射灯光的效果。
12.3D物理系统
12.1刚体组件介绍
介绍了刚体组件Rigidbody的中一些选项的功能。
Rigidbody组件中的Is Kinematic勾选上后,该物体将不会受到碰撞等效果的影响。
12.2刚体常用的方法
12.2.1Constant Forse组件
可以在该组件中设置不同方向的恒定力,Relative表示按照相对坐标的的方向确定力。
12.2.2添加刚体速度
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
rb.velocity = new Vector3(0, 0, 5);
}
}
该段代码的功能是,使脚本所挂的物体在世界坐标的Z轴方向以5的速度运动。
12.2.3添加力
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
rb.AddForce (new Vector3(0, 0, 10f));
}
}
该段代码的功能是在代码所挂的物体上添加一个世界坐标Z轴方向的大小为50的力。
若想添加相对坐标的Z轴的方向的力,可以将上述代码中的rb.AddForce(new Vector3(0, 0, 10f));改为rb.AddRelativeForce (new Vector3(0, 0, 10f));
若想添加世界坐标Z轴方向的扭矩力,可以将上述代码中的rb.AddForce(new Vector3(0, 0, 10f));改为rb.AddTorque (new Vector3(0, 0, 10f));
若想添加相对坐标Z轴方向的扭矩力,可以将上述代码中的rb.AddForce(new Vector3(0, 0, 10f));改为rb.AddRelativeTorque (new Vector3(0, 0, 10f));
ForceMode 力的模式
在unity中,Rigidbody.AddForce()实现对刚体物体施加力的效果,实现物体例如碰撞,爆炸等等效果
调用函数如下:
public void AddForce(Vector3 force, ForceMode mode = ForceMode.Force);
public void AddForce(float x, float y, float z, ForceMode mode = ForceMode.Force);
AddForce()函数有一个参数 ForceMode , 为枚举类型
Force:添加一个可持续力到刚体,使用它的质量
Acceleration:添加一个可持续加速度到刚体,忽略它的质量。
Impulse:添加一个瞬间冲击力到刚体 ,使用它的质量。( 爆炸或碰撞力量 )
VelocityChange:添加一个瞬间速度变化给刚体,忽略它的质量。
具体介绍如下:
在以下举例中均设刚体质量为m=2.0f,力向量为f=(10.0f,0.0f,0.0f)。
1 . ForceMode.Force:默认方式,使用刚体的质量计算,时间间隔以系统帧频间隔计算(默认值为0.02s)。
则由动量定理 f • t = m • v
可得:10 * 0.02 = 2.0 * v1,从而可得 v1=0.1 m/s,即每秒刚体在X轴上值增加0.1米
2 . ForceMode.Acceleration:忽略刚体的实际质量而采用默认值m = 1.0f,时间间隔以系统帧频间隔计算(默认值为0.02s)
则 f • t = 1.0 • v
可得:10 * 0.02 = 1.0 * v2,从而可得 v2=0.2 m/s,即每秒刚体在X轴上值增加0.2米
3 . ForceMode.Impulse:采用瞬间力作用方式,即默认 t = 1.0f,不再采用系统的帧频间隔
则 f • 1.0 = m • v
可得:10 * 1.0 = 2.0 * v3,从而可得 v3=5.0 m/s,即每秒刚体在X轴上值增加5.0米
4 . ForceMode.VelocityChange:忽略刚体的实际质量,采用默认值m = 1.0f,同时也忽略系统的实际帧频间隔,采用默认间隔 t = 1.0f
则 f • 1.0 = 1.0 • v
可得:10 * 1.0 = 1.0 * v4,从而可得 v4=10.0 m/s,即每秒刚体在X轴上值增加10.0米
12.2.4爆炸力
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetKeyDown("a"))
{
rb.AddExplosionForce(500f, transform.position, 10f);/*三个参数分别是:爆炸力度、爆炸位置、爆炸范围*/
}
}
}
该段代码的功能是在运行时按下A键后,组件所挂的物体在原位置受到一个大小为500f的力。
12.2.5刚体的唤醒和休眠
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetKeyDown("a"))
{
rb.Sleep();
}
else if (Input.GetKeyDown("b"))
{
rb.WakeUp();
}
}
}
该段代码实现的功能是,在运行状态下按A键,刚体组件将失效,再按B键刚体组件将恢复效果。
12.3碰撞器和触发器
12.3.1碰撞器组件介绍
1.点了碰撞器组件中的Is Trigger按钮后,碰撞器变为触发器。
2.触发和碰撞检测的条件
碰撞器条件:1.碰撞与被碰撞物体都需要有碰撞器组件且都不能勾选为触发器。2.挂脚本的物体上有刚体组件。
触发器条件:1.碰撞与被碰撞物体,至少有一个勾选为触发器。2挂脚本的物体上有刚体组件。
12.3.2碰撞器
示例
using UnityEngine;
public class Test : MonoBehaviour
{
private void OnCollisionEnter(Collision collision)
{
Debug.Log("I had collision");
}
}
该段代码的功能是,脚本所挂物体发生碰撞时控制台打印:我发生了碰撞。
若想在结束碰撞时调用控制台打印,可以将上述代码中的private void OnCollisionEnter(Collision collision)换成private void OnCollisionExit(Collision collision)。
若想在碰撞停留时调用控制台打印,可以将上述代码中的private void OnCollisionEnter(Collision collision)换成private void OnCollisionStay(Collision collision)。
12.3.3触发器
示例
using UnityEngine;
public class Test : MonoBehaviour
{
private void OnTriggerEnter(Collider collider)
{
Debug.Log("I had Trigger.");
}
}
该段代码的功能是,脚本所挂物体发生碰撞时控制台打印:我发生了触发。
若想在结束触发时调用控制台打印,可以将上述代码中的private void OnTriggerEnter(Collider collider)改为private void OnTriggerExit(Collider collider)。
若想在触发停留时调用控制台打印,可以将上述代码中的private void OnTriggerEnter(Collider collider)改为private void OnTriggerStay(Collider collider)。
12.3.4所碰撞物体
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public void OnCollisionEnter(Collision collision)
{
Debug.Log("Collision object is:" + collision.gameObject.name);
}
}
该段代码可以在运行时打印脚本所挂物体所碰撞的物体名称。
12.4力的常用函数
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Rigidbody rb;
void Start()
{
rb = transform.GetComponent<Rigidbody>();
Vector3 direction = transform.position + new Vector3(0, 1, 0) - transform.position;
rb.AddForceAtPosition(direction * 10f, transform.position);
}
}
该函数的功能是,使脚本所挂物体受到一个指定方向和作用点的力。
12.5物理材质
物理材质在Project>Creat>Physics Material中创建,创建后可以设置摩檫力、弹力等值,设置后拖入物体的Collider组件中,便可使组件具有该物理性质。
注意,当两个碰撞的物体设置了不同的结合方式时,采用的顺序如下: Average < Minimum < Multiply < Maximum,例如一个设置Minimum,一个设置Maximum,那么结合方式为Maximum。
12.6关节组件
12.6.1组件效果
固定关节组件(Fixed Joint):想两个物体用棍子连载一起。
弹簧关节组件(Spring Joint):像两个物体用弹簧连在一起。
铰链关节组件(Hinge Joint):像两个物体用铰链连在一起。
角色关节组件(Character Joint):可以模拟角色的骨骼关节。
可配置关节组件(Configurable Joint):可模拟任意关节效果。
12.6.2关节力度检测
检测断开的代码,脚本API:OnJointBreak
示例
using UnityEngine;
public class Test : MonoBehaviour
{
private void OnJointBreak(float force)
{
Debug.Log("Joint is break,force is:" + force);
}
}
该段代码的功能是在设置了关节断开的力度后,运行时断开会在控制台打印关节断开了,并显示断开时的力度。
12.7射线
12.7.1射线的绘制
第一种方式:
脚本API:Debug.DrawLine(起点位置,终点位置,颜色,持续时长,是否被遮挡);
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Debug.DrawLine(transform.position, new Vector3(5, 5, 5), Color.blue, 10,true);
}
}
上述脚本的功能是,在脚本所挂物体处发射一条终点坐标为(5,5,5)的,蓝色的,延迟10秒的,可被遮挡的射线。
第二种方式:
脚本API:Debug.DrawRay(起点位置,方向和长度,颜色,持续时长,是否被遮挡);
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Debug.DrawRay(transform.position,new Vector3(0,1,0),Color.blue,10,true);
}
}
上述脚本的功能是,在脚本所挂物体处发射一条朝(0,1,0)方向的,两点之间长度的,蓝色的,延迟10秒的,可被遮挡的射线。
12.7.2射线检测
1.检测单个物体
第一种方式
using UnityEngine;
public class Test : MonoBehaviour
{
Ray ray;
RaycastHit hit;
void Update()
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
Debug.Log("Mouse point attached to " + hit.transform.name);
}
}
}
将含上面代码的脚本挂到摄像机上,在运行时可以显示鼠标指向的物体的名称。
第二种方式
使用的API:Physics.Raycast(射线,光线碰到的物体out hit(类型RaycastHit),射线长度float,遮罩过滤层LayerMask)
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Camera camera;
void Start()
{
camera = GameObject.Find("Main Camera").GetComponent<Camera>();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = camera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100f))
{
Debug.Log("Hitted,Position is:" + hit.point + ",Object name is:" + hit.collider.gameObject.name);
}
else
{
Debug.Log("No hitted");
}
}
}
}
该段代码的功能是,在运行并用鼠标左键点击某处后如果发生了碰撞,控制台打印发生了碰撞,并打印碰撞的位置和碰撞的物体名称。
第三种方式
使用的API:Physics.Raycast(射线起点Vector3,射线方向Vector3,光线碰到的物体out hit(类型RaycastHit),射线长度float,遮罩过滤层LayerMask)
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public LayerMask layerMask;
void Start()
{
layerMask = LayerMask.GetMask("Boss");
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, 100f, layerMask))
{
Destroy(hit.collider.gameObject);
}
else
{
Debug.Log("miss hitted target");
}
}
}
}
创建两个物体,该两个物体的X,Y轴数值相同,将含上面代码的脚本挂到两个物体中Z轴数值小的物体上,在Inspector中将两个物体的Layer设置成“Boss”,在两个物体的中间加一个物体将两个物体隔开,将该物体的Layer设置成另一种,运行后点击鼠标左键,Z轴数值大的物体将被销毁。
2.检测多个物体
碰到的物体形成数组
用到的API:Physics.RaycastAll(射线,射线最大长度fioat,遮罩过滤层LayerMask)
也可以用:Physics.RaycastAll(射线起点Vector3,射线方向Vector3,射线长度float,遮罩过滤层LayerMask)
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit[] hit=Physics.RaycastAll(transform.position,transform.forward,100f);
for(int i = 0; i < hit.Length; i++)
{
Debug.Log("Hitted "+hit.Length+" object");
Debug.Log("No." + i + " name is " + hit[i].collider.gameObject.name);
}
}
}
}
该段代码的功能是将探测的物体组成一个数组,并通过控制台访问数组的信息。
3.球形射线
使用的API:Physics.OverlapSphere(transform.position,3f);
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Collider[] colliders = Physics.OverlapSphere(transform.position, 3f);
for(int i = 0; i < colliders.Length; i++)
{
Debug.Log("Hitted " + colliders.Length + " objects");
Debug.Log("No. " + i + " name is " + colliders[i].gameObject.name);
}
}
}
该段代码的功能是,检测一个球形内的碰撞体信息,并用控制台输出。
13.2D物理系统
13.1 2D的物理碰撞和触发器
13.1.1碰撞和触发的条件
碰撞的条件:两个物体都要带有碰撞器,其中一个需要有刚体。
触发的条件:碰撞的两个物体至少有一个勾选了Is Trigger选项。
13.1.2碰撞的生命周期
使用的脚本API:OnCollisionEnter2D
示例
using UnityEngine;
public class Player : MonoBehaviour
{
private void OnCollisionEnter2D(Collision2D collision)
{
Debug.Log("I collided "+collision.gameObject.name);
}
}
该段代码的功能是,在两个2D物体发生碰撞时,控制台打印进入碰撞和脚本所挂物体碰到的物体名称。
若想在碰撞结束时打印,可以将上述代码中的OnCollisionEnter2D改为OnCollisionExit2D。
若想在碰撞发生时打印,可以将上述代码中的OnCollisionEnter2D改为OnCollisionStay2D。
13.1.3触发的生命周期
使用的脚本API:OnTriggerEnter2D
示例
using UnityEngine;
public class Player : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D collision)
{
Debug.Log("I trigged " + collision.gameObject.name);
}
}
该段代码的功能是,在两个2D物体发生接触时,控制台打印进入接触和脚本所挂物体接触到的物体名称。
若想在接触结束时打印,可以将上述代码中的OnTriggerEnter2D改为OnTriggerExit2D。
若想在接触持续时打印,可以将上述代码中的OnTriggerEnter2D改为OnTriggerStay2D。
13.2 2D物理材质
讲了Project中新建的Physice Material 2D的使用。
13.3 2D效果器
讲了2D效果器组件,包括:
1.Area Effector 2D
2.Surface Effector 2D
3.Buoyancy Effector 2D
4.Point Effector 2D
13.4 2D物体中的其他碰撞器与恒力组件
讲了Capsule Collider 2D,Circle Collider 2D,Edge Collider 2D组件。
讲了Constant Force 2D组件。
13.5 脚本与2D刚体的交互
示例
using UnityEngine;
public class Player : MonoBehaviour
{
Rigidbody2D r2;
void Start()
{
r2 = transform.GetComponent<Rigidbody2D>();
}
void Update()
{
float x = Input.GetAxis("Horizontal");
float y = Input.GetAxis("Vertical");
if (x != 0 || y != 0)
{
r2.velocity = new Vector2(100 * x, 100 * y);
}
}
}
该段代码实现的功能是,通过WSAD来控制对象的上下左右移动。
14.动画系统
14.1动画的播放控制
14.1.1通过组件控制
导入模型后,在Project中新建一个Animator Controller,双击Animator Controller,将模型内部的动画文件拖入到Animator Controller的场景中,再将Animator Controller拖入到模型的Animator组件(如果没有该组件可以新创建一个)的Controller中,再点击运行模型即可动起来。
14.1.2通过脚本控制
示例
using UnityEngine;
public class Test : MonoBehaviour
{
Animator am;
void Start()
{
am = transform.GetComponent<Animator>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha0))
{
am.SetInteger("id", 0);
}
else if (Input.GetKeyDown(KeyCode.Alpha1))
{
am.SetInteger("id", 1);
}
else if (Input.GetKeyDown(KeyCode.Alpha2))
{
am.SetInteger("id", 2);
}
else if (Input.GetKeyDown(KeyCode.Alpha3))
{
am.SetInteger("id", 3);
}
else if (Input.GetKeyDown(KeyCode.Alpha4))
{
am.SetInteger("id", 4);
}
}
}
在Prooject中创建一个Animator Controller,将动画拖进Animator Controller中,在Animator中设置通过Any State设置动画的播放,在Parameter中设置一个名叫id的变量,点击Animater中的箭头,在Inspector中设置动漫所对应的值,并将Inspector>Setting>Can Transition To Self取消勾选,通过该代码可以实现在运行时,通过按设置的值实现相应的动画效果。
14.2人形动画
人形动画的特点是可以使用其他的人形动画。
14.3动画遮罩
动画遮罩的功能是屏蔽游戏对象某一部位的运动。
14.4动画的分层和退出控制
动画的分层控制是在Animator中添加多个Layer,并对各个Layer进行编辑,来对物体的动作进行分类控制。
14.5动画事件
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public void TestDebug()
{
Debug.Log("Test event");
}
}
可以在Project的动画文件的Inspector>Animatian>Events中添加动画事件,通过将脚本中的函数名(本例为TestDebug)粘贴至中Inspector>Animatian>Events>Founction中,运行后在动画播放到设置的位置时会激活函数。
15.寻路系统
15.1实现简单导航寻路功能
示例
using UnityEngine;
using UnityEngine.AI;
public class Test : MonoBehaviour
{
private NavMeshAgent agent;
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
bool iscollider = Physics.Raycast(ray, out hit);
if (iscollider)
{
agent.SetDestination(hit.point);
}
}
}
}
将地面物体的Inspector设置成Navigation Static.然后点击菜单Windows>AI>Navigation,将地面物体进行Bake.在待引导的物体上添加Nav Mesh Agent组件。将上述代码挂到待引导物体上,在运行时可以实现通过鼠标左键控制物体运动。
15.2导航面板参数介绍以及导航网格区域介绍
可以在Navigation>Areas中为不同区域添加不同的行走成本,再在Navigation>Object中设置道路成本类型,通过设置成本可以是物体智能的选择走哪条路。
15.3动态障碍物
将Nav Mesh Obstacle组件挂到一个阻碍物体上,并选中该组件中的Carve后,可以使待引导物体检测到阻碍物体而重新规划路线。
15.4分离导航连接线
在地面添加Off Mash Link组件,可以在该组件中设置两个点,设置好后待引导物体可以在这两个点之间移动。
15.5运动时动态烘培导航网格
需要用到Unity官方扩展的Navigation工具。
添加扩展工具后,可以添加NavMeshSurface组件,该组件生成导航网格不需要将地面物体设置成Navigation Static,并可以通过脚本动态生成物体并烘焙。
15.6其他组件功能介绍
Unity官方扩展的Navigation工具中的NavMashLink,该组件为OffMash Link的加强版,可以连接两个导航面。
16.音效系统
16.1音频源和音频监听器组件
音频播放可以选择在Hierachy中单独创建Audio Source物体,也可以选择在物体的Inspector中添加Audio Source组件来播放音频。
需要有Audio Listener组件方可听到播放的音频。
16.2音频源组件常用的函数
16.2.1常用功能
使用的API:
播放音频:AudioSours.Play();
暂停播放:AudioSours.Pause();
停止播放:AudioSours.Stop();
检测是否在播放:AudioSourse.isPlaying
示例
using UnityEngine;
public class Test : MonoBehaviour
{
AudioSource audio;
void Start()
{
audio = transform.GetComponent<AudioSource>();
}
void Update()
{
if (Input.GetKeyDown("a"))
{
if (audio.isPlaying == false)
{
audio.Play();
}
else
{
Debug.Log("Audio is playing,no need to play again.");
}
}
if (Input.GetKeyDown("b"))
{
audio.Pause();
}
if (Input.GetKeyDown("c"))
{
audio.Stop();
}
}
}
将该脚本挂入Audio Sourse物体后,可以实现按A键播放(如果已经在播放,则打印在播放),按B键暂停播放,按C键停止播放。
16.2.2指定音频剪辑
使用的API:AudioSource.clip
示例
using UnityEngine;
public class Test : MonoBehaviour
{
AudioSource audio;
void Start()
{
audio = transform.GetComponent<AudioSource>();
audio.clip = Resources.Load<AudioClip>("kuaidi1");
}
void Update()
{
if (Input.GetKeyDown("a"))
{
audio.Play();
}
}
}
该段代码的功能是,将Resources中的kuaidi1音频文件添加进组件,在游戏播放时按A键可以播放音频。
16.3音频过滤器和音频混响区
16.3.1音频过滤器
音频过滤器组件需要在有Audio Sources组件或Audio Listener组件的物体中才能添加。
16.3.2音频混响区
音频混响区组件Audio Reverb Zone,该组件可以设置在一定区域内的混响效果。
16.3.3音频管理器
打开方式:Edit>Project Setting>Audio.
11.3D模型管理
11.1蒙皮网格与普通网格对比
11.1.1对比
共同点:二者都可以通过关闭网格组件来隐藏物体
不同点:蒙皮网格适用于野怪等动画人物,普通网格适用于树等静态物,且普通网格有网格过滤器(Mesh filter),蒙皮网格没有。
11.1.2通过脚本控制网格组件的开关
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public void Start()
{
transform.GetComponent<MeshRenderer>().enabled = false;
}
}
在将脚本挂到对应的物体后,上述脚本实现的功能是在运行时将网格组件关闭使该物体不再显示,如果为动态物体,可以将上面的代码transform.GetComponent<MeshRenderer>().enabled= false;换成transform.GetComponent<SkinnedMeshRenderer>().enabled= false;
11.2材质的使用
新建或导入物体模型后,在Project中新建一个Material,将新建的Material导入到物体模型的Inspector>Mash Rander>Materials>Elements中,然后通过在新建的Marerial的Inspector中对材质进行Main Map>Albedo中导入图片,变换颜色等设置来改变物体材质。
11.2换肤功能的实现
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public MeshRenderer cube;
public Material material1;
public Material material2;
void Update()
{
if (Input.GetKeyDown("a"))
{
cube.material = material1;
}
if (Input.GetKeyDown("b"))
{
cube.material = material2;
}
}
}
将含上面代码的脚本挂到目标物体身上,并将目标物体拖入到脚本的MeshRenderer选项中,再将2套需要变换的材质分别拖入到脚本的material1和material2选项中,点击运行,按A键和按B键后可以实现皮肤的变换。
17.特效系统
17.1粒子系统
演示了一些粒子系统的效果。
创建粒子系统,Hierachy中点击右键Effect>Particle System.
17.2使用脚本和粒子系统交互
17.2.1基本交互
示例
using UnityEngine;
public class Test : MonoBehaviour
{
GameObject particleGO;
ParticleSystem particle;
void Start()
{
particleGO = GameObject.Instantiate(Resources.Load<GameObject>("22_RFX_Fire_Campfire1"));
particleGO.transform.position = transform.position;
particle = particleGO.GetComponent<ParticleSystem>();
ParticleSystem.MainModule mainModule = particle.main;
mainModule.loop = true;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
particle.Play();
}
if (Input.GetKeyDown(KeyCode.B))
{
particle.Stop();
}
if (Input.GetKeyDown(KeyCode.C))
{
particle.Pause();
}
if (Input.GetKeyDown(KeyCode.D))
{
Destroy(particleGO);
}
}
}
新建一个空物体,将含上面代码的脚本挂在空物体上,将名为22_RFX_Fire_Campfire的粒子特效预制体放入Projece/Resources文件夹中,可以实现在运行时将粒子特效预制体22_RFX_Fire_Campfire克隆并在点击A键时播放,B键时停止,C键时暂停,D键时销毁。
17.2.2碰撞回调
使用的API:OnParticleCollision(GameObject go)
示例
using UnityEngine;
public class Test : MonoBehaviour
{
private void OnParticleCollision(GameObject go)
{
Debug.Log("Particle had collision,collide to:" + go.name);
}
}
将该段代码挂到粒子系统物体的主子物体上,并将该主物体Inspector>Particle System>Collision勾选上,把Collision>Type设置成World,Collision>Mode设置成3D,Collision>Send Collision Messages勾选上,在粒子上方放一物体,运行时控制台会打印粒子发生了碰撞和碰撞到的物体名称。
17.3粒子触发回调
示例
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
ParticleSystem particle;
void Start()
{
particle = transform.GetComponent<ParticleSystem>();
}
private void OnParticleTrigger()
{
List<ParticleSystem.Particle> particles = new List<ParticleSystem.Particle>();
int numEnter = particle.GetTriggerParticles(ParticleSystemTriggerEventType.Enter, particles);
for (int i = 0; i < numEnter; i++)
{
ParticleSystem.Particle pt = particles[i];
pt.startColor = Color.red;
particles[i] = pt;
}
particle.SetTriggerParticles(ParticleSystemTriggerEventType.Enter, particles);
}
}
在粒子系统上方放一个物体,将该物体拖入粒子系统的Inspector>Particle System>Triggers>Colliders中,将Inspector>Particle System>Triggers>Enter设置成Callback,将含上面代码的脚本挂载到粒子系统物体上,运行时可以使粒子进入物体后变成红色。
17.4特效系统之拖尾
使用的API:TrailRenderer
示例
using UnityEngine;
public class Test : MonoBehaviour
{
GameObject go;
void Start()
{
go = GameObject.Instantiate(Resources.Load<GameObject>("Accelerate"));
go.transform.SetParent(transform);
go.transform.localPosition = new Vector3(0, 0.5f, 0);
}
void Update()
{
if (Input.GetKeyDown("a"))
{
go.GetComponent<TrailRenderer>().emitting = true;
}
if (Input.GetKeyDown("b"))
{
Destroy(go);
}
}
}
新建一个物体,将含上面代码的脚本挂载到该物体上,准备一个拖尾的预制体Accelerate放入Resources文件夹中,在运行时按下A键可以激活克隆的Accelerate,使拖动时表现出效果,按下B键时销毁克隆的Accelerate。
17.5特效系统之粒子力场
讲了Hierachy中点击右键Effect>Particle System Force Field的相关知识点。
18.视频播放管理
18.1视频播放方法
在场景中新建RawImage,在RawImage中添加Video Player组件,在Assets中新建Render Texture,将Render Texture和视频资源分别放入Raw Image和Video Player组件中,点击即可播放。
18.2视频组件常用的函数
18.2.1视频播放常用操作
示例
using UnityEngine;
using UnityEngine.Video;
public class Test : MonoBehaviour
{
VideoPlayer video;
void Start()
{
video = transform.GetComponent<VideoPlayer>();
}
void Update()
{
if (Input.GetKeyDown("a"))
{
if (video.isPlaying == false)
{
video.Play();
}
else
{
Debug.Log("Video is playing,no need to play again");
}
}
if (Input.GetKeyDown("b"))
{
video.Pause();
}
if (Input.GetKeyDown("c"))
{
video.Stop();
}
}
}
将该段代码挂到有Video Player组件的物体中,在运行时可以通过按键实现播放,暂停,停止等
18.2.2视频播放组件设置
示例
using UnityEngine;
using UnityEngine.Video;
public class Test : MonoBehaviour
{
VideoPlayer video;
void Start()
{
video = transform.GetComponent<VideoPlayer>();
video.source = VideoSource.VideoClip;
video.clip = Resources.Load<VideoClip>("GameExplain");
}
}
将视频剪辑文件GameExplain放入Resources文件夹,将组件Video Player>Source设置成URL,通过该段代码可以实现在运行时Video Player>Source切换至Video Clip模式,并播放素材名为GameExplain的视频。
19.DoTween补间动画插件
19.1空间物体位置旋转大小等动画
19.1.1位置
使用的API:DOMove(位置,时间)
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOMove(new Vector3(10, 10, 10), 2f);
}
}
当前代码的功能是将脚本所挂物体用2秒移动到世界坐标系(10,10,10)位置。
如果想以本地坐标系作为参考,可以将上面代码中的transform.DOMove(new Vector3(10,10,10), 2f);换成transform.DOLocalMove(new Vector3(10,10,10), 2f);
如果想将物体沿X轴移动,可以将上面代码中的transform.DOMove(new Vector3(10,10,10), 2f);换成transform.DOLocalMoveX(10, 2f);
如果想让物体匀速运动,需要将transform.DOMove(new Vector3(10, 10, 10), 2f);改为transform.DOMove(new Vector3(10, 10, 10), 2f).SetEase(Ease.Linear);
19.1.2旋转
使用的API:DORotate(角度,时间)
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DORotate(new Vector3(0, 20, 0), 2f);
}
}
当前代码的功能是将脚本所挂物体用2秒沿世界坐标系的Y轴顺时针转20度。
如果想以本地坐标系为参考旋转,可以将上面代码中的transform.DORotate(new Vector3(0, 20, 0), 2f);改为transform.DOLocalRotate(new Vector3(0, 20, 0), 2f);
19.1.3缩放
使用的API:DOScale(缩放倍数,时间)
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOScale(new Vector3(6, 6, 6), 2f);
}
}
该段代码的功能是,将脚本所挂物体的X,Y,Z轴三个方向都缩放至6倍.
如果只想让X轴方向缩放至6,可以将上面代码中的transform.DOScale(new Vector3(6, 6, 6), 2f);换成transform.DOScaleX (6, 2f);
19.1.4跳跃
使用的API:DOJump(跳跃目的地位置,跳跃高度,步数,时间)
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOJump(new Vector3(60, 0, 0), 1,5,6);
}
}
该段代码的功能是,使脚本所挂物体在6秒内以Y轴方向1高度分5步跳到指定位置。
如果想以当地坐标系为参考,可以将上面代码中的transform.DOJump(new Vector3(60,0,0),1,5,6);换成transform.DOLocalJump(new Vector3(60,0,0),1,5,6);
19.1.5弹簧冲击
使用的API:DOPunchPosition(位置, 时间, 频率, 对侧弹性);
DOPunchRotation(new Vector3(角度,时间, 频率, 对侧弹性);
transform.DOPunchScale(缩放倍数, 时间, 频率, 对侧弹性);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOPunchPosition(new Vector3(10, 0, 0), 3,10,1);
}
}
该段代码实现的功能是,使脚本所挂物体用3秒,每秒10次,以最大的弹性的来回弹跳。
如果想实现物体的角度弹簧冲击,可以将上面代码中的transform.DOPunchPosition(new Vector3(10, 0, 0), 3, 10, 1);换成transform.DOPunchRotation(new Vector3(10, 0, 0), 3, 10, 1);
如果想实现物体缩放的弹簧冲击,可以将上面代码中的transform.DOPunchPosition(new Vector3(10, 0, 0), 3, 10, 1);换成transform.DOPunchScale(new Vector3(10, 0, 0), 3, 10, 1);
19.1.6旋转
使用的API:.DOLookAt(旋转的方向,时间);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOLookAt(new Vector3(1,1,1), 2f);
}
}
该段代码实现的功能是用2秒沿着指定方向自旋转。
19.1.7增量
使用的API:DOBlendableMoveBy(位置增量, 时间);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOBlendableMoveBy(new Vector3(20,0,0), 2f);
}
}
该段代码的功能是,是脚本所挂物体用2秒在X轴方向的坐标增加20。
如果想实现旋转角度的增量,可以将上面代码transform.DOBlendableMoveBy(new Vector3(20, 0, 0), 2f);换成transform.DOBlendableRotateBy(new Vector3(20, 0, 0), 2f);
如果想实现缩放的增量,可以将上面代码transform.DOBlendableMoveBy(new Vector3(20, 0, 0), 2f);换成transform.DOBlendableScaleBy(new Vector3(20, 0, 0), 2f);
19.2颜色、透明度的控制
19.2.1颜色
使用的API:DOColor(颜色,时间);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Material material = GetComponent<MeshRenderer>().material;
material.DOColor(Color.red, 2f);
}
}
该段代码的功能是用两2秒将脚本所挂物体变成红色。
该方法也可用于文本和图片颜色的更改。
19.2.2透明度
使用的API:DOFade(透明度,,时间);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Material material = GetComponent<MeshRenderer>().material;
material.DOFade(0, 2f);
}
}
将脚本所挂物体的Inspector>Shader修改成Lagacy Shader>TransParent>Diffuse,通过上面的代码可以用2秒将脚本所挂物体隐形。
19.2.3颜色渐变
使用的API:
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
public Gradient gradient;
void Start()
{
Material material = GetComponent<MeshRenderer>().material;
material.DOGradientColor(gradient, 2f);
}
}
定义了公开变量gradient后,在Unity中Inspector中找到gradient并设置该渐变色,设置完成后运行,该段代码功能是使脚本所挂物体的颜色用2秒渐变。
19.3震动效果表现
19.3.1物体震动
使用的API:DOShakePosition(时间, 振幅,频率,混乱程度);
transform.DOShakeRotation(时间, 角幅度,频率,混乱程度);
transform.DOShakeScale(时间, 大小幅度,频率,混乱程度);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOShakePosition(2f, 1, 10, 90);
}
}
该段代码实现的功能是,使脚本所挂物体用2秒以1振幅,10振幅,90混乱度的状态震动。
如果想换成方向震动,可以将上述代码中的transform.DOShakePosition(2f, 1, 10, 90);换成transform.DOShakeRotation(2f, 90, 10, 90);
如果想换成大小震动,可以将上述代码中的transform.DOShakePosition(2f, 1, 10, 90);换成transform.DOShakeScale(2f,2, 10, 90);
19.3.2摄像机震动
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
transform.DOShakePosition(2f, 1, 10, 90);
}
}
定义了摄像机后,将指定摄像机拖入该变量中,通过该段代码可以实现摄像机的震动。
参考上一小节,同理可实现摄像机的角震动。
19.4物体路径动画
使用的API:DOPath(路径,时间,路径类型,路径模式,分辨率,颜色);
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Vector3[] path = new Vector3[] { new Vector3(1, 2, 1), new Vector3(2, 1, 3), new Vector3(10, 2, 5), new Vector3(4, 9, 6) };
transform.DOPath(path, 5,PathType.Linear,PathMode.Full3D,10,Color.red);
}
}
该段代码的功能是,使脚本所挂物体以设置的模式沿路径运动
除了用脚本控制物体运动外,还可以通过Dotween Path组件来控制物体的运动。
19.5动画序列Sequence
19.5.1动画序列
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Sequence sequence = DOTween.Sequence();
sequence.Append(transform.DOMoveX(10,1));
sequence.Insert(0,transform.DOScale(2,1));
sequence.AppendInterval(2);
sequence.Append(transform.DOMoveX(0,1));
sequence.Insert(3,transform.DOScale(1,1));
}
}
该段代码实现的功能是,用1秒钟使被挂脚本的物体在X轴移动到10的位置,同时大小变为原来的2倍,停顿两秒后,物体X轴的位置变为0,同时大小变回原来的大小。
上面代码中Insert方法也可以用Join方法来实现同样的功能,只需将代码sequence.Insert(0, transform.DOScale(2, 1));换成sequence.Join(transform.DOScale(2, 1));并将sequence.Insert(3,transform.DOScale(1, 1));换成sequence.Join(transform.DOScale(1, 1));即可。
19.5.2方法回调
Append回调:
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Sequence sequence = DOTween.Sequence();
sequence.Append(transform.DOMoveX(10,1));
sequence.Join(transform.DOScale(2,1));
sequence.AppendCallback(() =>
{
Debug.Log("AppendCallback1");
});
sequence.Append(transform.DOMoveX(0,1));
sequence.Join(transform.DOScale(1,1));
sequence.AppendCallback(() =>
{
Debug.Log("AppendCallback2");
});
}
}
AppendCallback会在上面的代码执行完后调用。
Insert回调:
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Sequence sequence = DOTween.Sequence();
sequence.Append(transform.DOMoveX(10,1));
sequence.Insert(0,transform.DOScale(2,1));
sequence.AppendInterval(2);
sequence.Append(transform.DOMoveX(0,1));
sequence.Insert(3,transform.DOScale(1,1));
sequence.InsertCallback(6,() =>
{
Debug.Log("InsertCallback2");
});
}
}
该段代码会在运行6秒后打印InsertCallback,即InsertCallback的执行时间点只与填写的时间点有关。
19.6动画常用设置以及动画控制
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
Tweener tweener;
void Start()
{
tweener=transform.DOMoveX(10,1).SetEase(Ease.Linear).SetLoops(-1,LoopType.Restart).SetDelay(0).SetAutoKill(true);
}
private void onGUI()
{
if (GUILayout.Button("暂停"))
{
tweener.Pause();
}
if (GUILayout.Button("Kill"))
{
tweener.Kill();
}
if (GUILayout.Button("播放"))
{
tweener.Play();
}
if (GUILayout.Button("倒回播放"))
{
tweener.PlayBackwards();
}
if (GUILayout.Button("向前播放"))
{
tweener.PlayForward();
}
if (GUILayout.Button("重新播放"))
{
tweener.Restart();
}
if (GUILayout.Button("回到初始位置"))
{
tweener.Rewind();
}
if (GUILayout.Button("跳转到"))
{
tweener.Goto(2);
}
if (GUILayout.Button("点击暂停"))
{
tweener.TogglePause();
}
}
}
该段代码的功能是,设置一段动画,并通过不同的按键来控制动画。(运行问题:游戏页面无法形成控制按钮)
21.各平台打包操作
21.1Windows平台
讲解了Windows平台的打包操作
21.2安卓平台
安卓平台的打包需要先在Hub中安装Android SDK & NDK Tools和Open JDK两个组件。
21.3IOS平台
讲解了IOS平台的打包操作
19.7动画的回调
示例
using DG.Tweening;
using UnityEngine;
public class Test : MonoBehaviour
{
Tweener tweener;
void Start()
{
tweener=transform.DOMoveX(10,1).SetEase(Ease.Linear).SetLoops(-1,LoopType.Restart).SetDelay(0).SetAutoKill(true);
tweener.OnComplete(() =>
{
Debug.Log("OnComplete");
});
tweener.OnKill(() =>
{
Debug.Log("OnKill");
});
tweener.OnPlay(() =>
{
Debug.Log("OnPlay");
});
tweener.OnStart(() =>
{
Debug.Log("OnStart");
});
tweener.OnRewind(() =>
{
Debug.Log("OnRewind");
});
tweener.OnUpdate(() =>
{
Debug.Log("OnUpdate");
});
tweener.OnPause(() =>
{
Debug.Log("OnPause");
});
}
}
该段代码的功能是根据动画运行时的不同状态打印相应的提示。
20.EasyTouch手势插件
20.1手势监测之初级使用
示例
using HedgehogTeam.EasyTouch;
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
Gesture gesture = EasyTouch.current;
if (gesture != null)
{
if (EasyTouch.EvtType.On_TouchStart == gesture.type)
{
OnTouchStart(gesture);
}
else if (EasyTouch.EvtType.On_Drag == gesture.type)
{
OnDragStart(gesture);
}
}
}
private void OnTouchStart(Gesture gesture)
{
Debug.Log(gesture.type);
}
private void OnDragStart(Gesture gesture)
{
Debug.Log(gesture.type);
}
}
上述代码的功能是,当运行时鼠标点击或者拖拽被挂脚本物体,控制台打印相关信息。
20.2手势监测之使用QuickGesture以及Trigger
20.2.1QuickGesture类组件
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public void Log(string str)
{
Debug.Log(str);
}
}
新建一个空物体,讲脚本挂入空物体中,然后将空物体挂入待操作物体的Quick Drag,Quick Tap,Quick Touch,Quick Pinch等组件中,设置相关输出内容,在运行时进行对物体进行操作后,会输出相关内容。
20.2.2Trigger组件
示例
using UnityEngine;
public class Test : MonoBehaviour
{
public void Log(int str)
{
Debug.Log(str);
}
}
将含该代码的脚本挂入待操作物体上,并在待操作物体上加入Trigger组件,选择Add new event>On_Touch Start,将Mothed name改成Log,将Parameter to send改为Touch_Count,在运行时将对物体的操作信息通过控制台打印。
20.3组件核心参数
讲解了Easy Touch组件
20.4JoyStick虚拟摇杆
讲解了ETCJoystick组件
22.各平台调试技术
22.1常见的异常
22.1.1空指针导致的异常
空指针异常可以分为未指定引用对象(包括未指定和未分配对象),和指定的路径错误(包括查找物体和查找资源)两类。
22.1.2数据结构错误
包括重复添加相同的Key和索引出现异常。
22.2编辑器模式下的日志功能
日志的三种类型:
普通日志:Debug.Log("普通日志");
警告日志:Debug.LogWarning("警告日志");
错误日志:Debug.LogError("错误日志");
22.3安卓平台下的日志跟踪
分为Unity本身的调试和AndroidStudio调试。
22.4IOS调试日志查看
讲解了IOS平台下的日志查看。
22.5断点调试和调用堆栈
22.5.1断点调试
在一些代码前面加入断点,点击附加到Unity,在Unity中点击播放,返回Visual Studio中查看相关代码的值。
22.5.2调用堆栈
在Visual Studio中操作
23.其他知识
23.1生成随机数
示例
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
for(int i = 0; i < 10; i++)
{
Debug.Log(Random.Range(0,8));
}
}
}
该段代码的功能是在运行时控制台随机打印10个0~7之间的随机数。
23.2协程方法
示例1
using System.Collections;
using UnityEngine;
public class Test : MonoBehaviour
{
private void Start()
{
StartCoroutine(MyCoroutine(2, "success"));
}
IEnumerator MyCoroutine(int i, string str)
{
Debug.Log(i);
yield return new WaitForSeconds(5f);
Debug.Log(str); // 打印i的5s后执行
yield return new WaitForSeconds(5f);
Debug.Log("123"); // 打印str的5s后执行
}
}
该段代码的功能是间隔一定时间打印内容。
示例2
using System.Collections;
using UnityEngine;
public class Test : MonoBehaviour
{
private void Start()
{
StartCoroutine(MyCoroutine(2));
}
IEnumerator MyCoroutine(int i)
{
while (true)
{
yield return new WaitForSeconds(1);
Debug.Log(i);
}
}
}
该段代码的作用是每过1秒打印一次数字2.
23.3调用方法
示例1
using UnityEngine;
public class Test : MonoBehaviour
{
private void Start()
{
Invoke("Bigger",2);
}
void Bigger()
{
transform.localScale = new Vector3(2, 2, 2);
}
}
该代码的作用是使脚本所挂物体在2秒后变为原来的2倍。
示例2
using UnityEngine;
public class Test : MonoBehaviour
{
private void Start()
{
InvokeRepeating("Bigger",2,1);
}
void Bigger()
{
transform.localScale += new Vector3(1, 1, 1);
}
}
该代码的作用是使脚本所挂物体2秒后增大1倍,然后每1秒增大1倍。
示例3
using UnityEngine;
public class Test : MonoBehaviour
{
private void Start()
{
InvokeRepeating("Fuse", 0.01f,0.01f);
}
private void Fuse()
{
transform.Translate(new Vector3(0.02f, 0.02f, 0.02f));
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
CancelInvoke();
}
}
}
该段代码的功能是,使物体持续朝一个方向运动,在按下鼠标左键后停止运动。
23.3触发器
示例
using UnityEngine;
public class zidan : MonoBehaviour
{
void OntriggerEnter(Collider coll)
{
if (coll.name == "Cube")
{
//transform.position 生成一个特效到这个位置上
Destroy(transform.gameObject);
}
else if (coll.name == "xiaonuhai")
{
//transform.position 生成一个别的特效到这个位置上
Destroy(transform.gameObject);//打中小女孩后,销毁子弹
Destroy(coll.gameObject);//打中小女孩后,销毁小女孩
}
}
}
23.5按键控制程序退出
示例
using UnityEngine;
using UnityEngine.UI;
public class Exit : MonoBehaviour
{
void Start()
{
transform.GetComponent<Button>().onClick.AddListener(() => { DoExit(); });
}
void DoExit()
{
UnityEditor.EditorApplication.isPlaying= false;
Application.Quit();
}
}
上述代码的功能是,当按键被按下时,退出游戏。
23.6Text中显示时间
示例
using System;
using UnityEngine;
using UnityEngine.UI;
public class ShowTime : MonoBehaviour
{
public Text time1;
void Update()
{
DateTime nowTime=DateTime.Now.ToLocalTime();
time1.text = nowTime.ToString("yyyy-MM-dd HH:mm:ss");
}
}
上述代码可以实现在Text中显示实时时间。
23.7Text字体隐形显现转换
示例
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
public class FlashWord : MonoBehaviour
{
private void Start()
{
Pingpong(1, 0, 0.6f);
}
void Pingpong(float fromValue, float toValue, float duration)
{
Color temColor = gameObject.GetComponent<Text>().color;
temColor.a = fromValue;
Tweener tweener = DOTween.ToAlpha(() => temColor, x => temColor = x, toValue, duration);
tweener.onUpdate = () => { gameObject.GetComponent<Text>().color = temColor; };
tweener.onComplete = () =>
{
Pingpong(toValue, fromValue, duration);
};
}
}
上述代码可以实现将字体的显隐变换效果,将<Text>改为<Image>可以实现图片的显隐效果。
23.8关闭程序
示例
using UnityEngine;
using UnityEngine.UI;
public class Exit : MonoBehaviour
{
void Start()
{
transform.GetComponent<Button>().onClick.AddListener(() => { DoExit(); });
}
void DoExit()
{
// UnityEditor.EditorApplication.isPlaying= false;
Application.Quit();
}
}
上述代码可以实现点击按键关闭程序。“//”后的代码加上后可以实现在编辑器模式下的关闭效果,但加上后无法打包成安卓应用。
23.9实现UI圆点跟随运动
示例
using System.Collections;
using DG.Tweening;
using UnityEngine;
public class AfterScanDotsMove : MonoBehaviour
{
public Transform[] Dots;
Vector3[] tempvec3;
void Start()
{
tempvec3 = new Vector3[Dots.Length];
StartCoroutine(DotsMove());
}
IEnumerator DotsMove()
{
while (true)
{
for (int i = 0; i < Dots.Length; i++)
{
tempvec3[i] = Dots[i].position;
}
for (int i = 0; i < Dots.Length; i++)
{
if (i < Dots.Length - 1)
{
Dots[i].transform.DOMove(tempvec3[i + 1], 0.5f).SetEase(Ease.Linear);
}
else
{
Dots[i].transform.DOMove(tempvec3[0], 0.5f).SetEase(Ease.Linear);
}
}
yield return new WaitForSeconds(0.5f);
}
}
}
该代码可以实现小圆点的跟随运动。
23.10全局变量
//该脚本不用挂载,内数据不会随场景变化而变化
public class storeData
{
public static int countData = 0;
}
//其他脚本可以使用这个数据
if (storeData.countData ==0)
23.11单例(一个脚本调另一个脚本里的变量或方法)
示例
//待调用的代码
using UnityEngine;
public class Juse : MonoBehaviour
{
public static Juse m_Instance;
void Start()
{
m_Instance = this;
}
public void OpenPage()
{
//待调用的方法
}
}
//调用的代码
using UnityEngine;
public class TimeShow : MonoBehaviour
{
void Start()
{
Juse.m_Instance.OpenPage();
}
}
23.12SendMessenger方法调用
示例
//待调用的脚本代码
using UnityEngine;
public class TakeMess : MonoBehaviour
{
public void DebugWord(string str)
{
Debug.Log(str);
}
}
//调用的脚本代码
using UnityEngine;
public class SendMess : MonoBehaviour
{
void Start()
{
GameObject.Find("Cube").SendMessage("DebugWord", "juse");
}
}
该代码可以调用Cube物体上的DebugWord方法,并传递相关参数。
若想调用自身及子物体上的方法,可以用BroadcastMessage( );
若想调用自身及父物体上的方法,可以用SendMessageUpwards( );
23.13List使用
List也叫列表,
23.14Dictionary使用
Dictionary也叫字典。
23.15Event Trigger组件
通过Event Trigger组件来控制鼠标的事件
23.16UI小窗口显示
再UI界面建一个Row Image,Hierarchy上新建一个摄像机,Project上新建一个Render Texture,将Render Texture分别挂在摄像机和Row Image上,就可以在Row Image上显示摄像机摄的东西。
23.17AssetBundle
1.打包
将要打包的资源在inspector中的预览窗口下设置要打包在AssetBundles下的路径和后缀名(可任意取)。新建一个C#脚本,脚本内容如下:
using System.IO;
using UnityEditor;
public class CreateAssetBundles
{
[MenuItem("Assets/Build AssetBundles")]//生成菜单目录
static void BuildAllAssetBundles()
{
string assetBundleDirectory = "Assets/AssetBundles";//指定AssetBundles文件夹的目录
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);//如果没有,则创建文件夹
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows);
}
}
脚本无需挂载,在菜单Assets下点击新创建的Build AssetBundles,即可在指定文件夹创建AssetBundle.
2.读取
场景中物体上挂载一个脚本,脚本代码如下:
using UnityEngine;
public class LoadAssetBundle : MonoBehaviour
{
void Start()
{
AssetBundle bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/this/wall.ab");//找到AB包
GameObject cubeWall = bundle.LoadAsset<GameObject>("CubeWall");//找到AB包中的物体
Instantiate(cubeWall);//实例化物体
}
}
运行后即可实例化物体。
标签:UnityEngine,入门,void,transform,笔记,物体,using,public From: https://www.cnblogs.com/gatran/p/17205581.html