Unity2019 从零到精通视频学习笔记
该文对Unity2019 做简单的自学了解,并做相应的笔记
一、C#基础回顾
-
基本数据结构
-
简单的控制台程序 namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
System.Console.WriteLine("Hello World");
}
}
}
-
类型转换 //int->string
int a = 10;
string strA = a.ToString();
//string->int
String b = "10";
int iB = int.Parse(b);
//使用Convert转换
iB = Convert.ToInt32(b);
-
数组 //一维数组
int[] a = { 1, 2, 3, 4, 5 };
int[] b = new int[5];//注意,只声明数组长度
Array.Copy(a, b, 5);//b的元素必须提前声明好
foreach(int i in b)
{
System.Console.WriteLine(i);
}
System.Console.WriteLine("{0}, 找到1首次出现的位置:{1}", b[0], Array.IndexOf(b, 1));
//多维数组
int[,] c = { { 1, 2, 3 }, { 4, 5, 6 } };
System.Console.WriteLine(c[0, 1]);
//string和stringbuilder
String name = "wang", name2 = "li";
StringBuilder names = new StringBuilder();
names.Append(name);
names.Append(name2);
System.Console.WriteLine(names);
-
面向对象数据结构
-
基本使用 class Test
{
private String strTitle;
public string GetMessage()
{
return "Message";
}
public string title
{
get
{
return strTitle;
}
set
{
strTitle = value;
}
}
}
-
ref和param class Program
{
/// <summary>
/// 测试使用REF,传递引用类型
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
static void TestRef(ref int a, ref int b)
{
int tmp = a;
a = b;
b = tmp;
}
/// <summary>
/// 测试使用params,传递无限制参数列表
/// </summary>
/// <param name="names"></param>
static void TestParam(params String[] names)
{
foreach(string name in names)
{
System.Console.WriteLine(name);
}
}
static void Main(string[] args)
{
int a = 10, b = 15;
TestRef(ref a, ref b);
System.Console.WriteLine("{0}, {1}", a, b);
TestParam("zhang", "li", "wang");
}
}
-
继承和多态
- abstract适合写非纯虚函数,interface适合写纯虚函数
- C#没有public、protect、private继承
- C#不存在多继承,只能继承一个类和多个接口
interface Study
{
void Read();
void Listen();
void Say();
void Write();
}
abstract public class People
{
private string name;
private int age;
public People(string name, int age)
{
this.name = name;
this.age = age;
}
abstract public void Hello();
}
sealed public class Student: People, Study
{
Student(string name, int age): base(name, age)
{
}
public override void Hello()
{
System.Console.WriteLine("Hello");
}
public void Listen()
{
}
public void Read()
{
}
public void Say()
{
}
public void Write()
{
}
}
-
集合索引和泛型 //使用arraylist,注意这种类型可以插入任何类型,但需要拆包
//如果不希望拆包,可以使用Array<int>
ArrayList arrayList = new ArrayList(5);
arrayList.Add(1);
int b = (int)arrayList[0];
//使用Stack
Stack objStack = new Stack();
Stack<int> iStack = new Stack<int>();
//使用Queue
Queue queue = new Queue();
//使用List(必须要指定类型)
List<int> iList = new List<int>();
//使用Dictonary(必须要指定类型)
Dictionary<int, string> keyValuePairs = new Dictionary<int, string>();
-
泛型 //这里使用where是一种约束,也就是T必须继承自Interface1
class TempClass<T> where T: Interface1
{
void TestSay(T obj)
{
obj.Say();
}
}
-
反射
- 一般不建议使用反射,反射破坏程序的封装性
- 反射可以遍历程序的名称,函数名等,也可以直接根据程序名创建对象和调用函数
public class Test
{
private string name;
public Test(String name)
{
this.name = name;
}
public void Print()
{
System.Console.WriteLine(this.name);
}
}
static void Main(string[] args)
{
//创建程序集名
Test t = new Test("t");
Type type = t.GetType();
System.Console.WriteLine(type);
//根据程序集名创建对象
Type type2 = Type.GetType("ConsoleApp1.Program+Test");
object[] constStructParams = new object[] { "t2" };
Object t2 = Activator.CreateInstance(type2, constStructParams);
((Test)t2).Print();
//指定函数名调用
MethodInfo info = type2.GetMethod("Print");
object[] constStructParams2 = new object[] { };
info.Invoke(t2, constStructParams2);
}
-
异常处理
-
事件
-
事件和委托
- delegate相当于函数指针,可以指向多个函数,可以在内部或外部调用。
- event只能在内部调用。
class Program
{
class EventTest
{
public delegate void GetMessage(string msg);
public GetMessage GetMessageDelegate;
public event GetMessage GetMessageEvent;
public void RaiseEvent()
{
GetMessageEvent("Hello");
}
}
static void Main(string[] args)
{
EventTest test = new EventTest();
test.GetMessageDelegate += OnGetMessage;
test.GetMessageDelegate("Delegate");
test.GetMessageEvent += OnGetMessage;
test.RaiseEvent();
}
static void OnGetMessage(string msg)
{
System.Console.WriteLine("OnGetMessage: {0}", msg);
}
}
-
异步编程
-
线程
- 线程
class Program
{
static void Main(string[] args)
{
{
Thread t = new Thread(new ThreadStart(Run));
t.Start();
}
{
Thread t = new Thread(new ThreadStart(new ThreadTest().MyThread));
t.Start();
}
{
Thread t = new Thread(new ThreadStart(delegate()
{
Console.WriteLine("匿名委托");
}));
t.Start();
}
{
Thread t = new Thread(()=>Console.WriteLine("箭头函数"));
t.Start();
}
{
Thread t = new Thread(new ParameterizedThreadStart(RunPara));
t.IsBackground = true;//后台线程,程序可以直接退出而不等线程结束
t.Start("向线程中传递参数,参数必须是Object类型");
t.Join();
}
}
static void Run()
{
Console.WriteLine("静态函数");
}
static void RunPara(object str)
{
Console.WriteLine(str);
}
}
class ThreadTest
{
public void MyThread()
{
Console.WriteLine("成员函数");
}
}
-
匿名委托,lambda表达式,Action和Func
- 匿名委托和lambda表达同价
- Action和Func可以直接定义函数传入参数的类型,Func要求必须有返回结果,Action要求没有返回结果。
- Delegate和Action、Func相比,多出了一次声明函数类型的过程。
- 定义event可以使用Action或Func代替delegate
public delegate void FuncDelegate(int c);
static void Main(string[] args)
{
Func<int, int> func = delegate (int c) { return c; };
Action<int> action = (int a) => { Console.WriteLine(a); };
FuncDelegate funcDelegate = delegate (int a) { Console.WriteLine(a); };
}
-
async/await
- aysnc和await和Task配合使用。
- await必须在async的函数中使用。
- 一般不会使用Task去获取Result,这样会造成线程卡死。
class Program
{
static void Main(string[] args)
{
{
//直接使用Task,获取异步返回结果
Task<int> task1 = new Task<int>(() => {
return 1;
});
task1.Start();
Console.WriteLine(task1.Result);
}
{
Console.WriteLine(GetResultAsync().Result);
}
}
static public async Task<int> GetResultAsync()
{
//Task<int> task = new Task<int>(()=> { return 1; });
Task<int> task = Task.Run<int>(() => { return 1; });
return await task;
}
}
-
协程
- 目前C#本身并没有有关协程的定义,在Unity3D库中有定义。
-
数据库和文件操作
- ADO和LINQ
- ADO主要突出了对数据库的操作。LINQ将SQL语句和C#语句融合在了一起,简化了操作的处理。
- 文件操作
- 文件操作使用StreamReader和StreamWriter操作。
二、引擎基本介绍
-
本次学习使用引擎是Unity 2019.2.12f1版本。 -
建议使用Unity Hub来管理Unity版本和授权。 -
Unity官网是unity.cn -
Unity在场景的操作方式和UE4基本一致 -
在[Unity - Manual: Order of Execution for Event Functions](file:///D:/Program Files/Unity/2019.2.12f1/Editor/Data/Documentation/en/Manual/ExecutionOrder.html)可以找到事件函数的执行顺序

Awake:不管脚本是否激活,都会被执行
Start:游戏开始
Update:游戏刷新的时候
FixedUpdate:固定刷新,0.02s调用一次
LateUpdate:在Update之后被调用
-
素材管理
-
导入导出图片
- 导入新资源
- 向场景中插入UI.Button
- 将图片类型设置成UI/Sprit
- 将图片应用于按钮
-
视频和音频

-
字体和粒子特效
-
模型和场景
- 一般注意如果是自己导入FBX和贴图,先导入贴图,然后导入FBX,才能实现绑定材质。
-
脚本
- 可以使用Debug.Log打印日志查看问题。
- 可以选择出错后终止,查看问题。
- 可以选择附加到Unity,在任何地方断点调试。
三、场景管理
-
同步加载场景 -
异步加载场景 -
加载场景时保留物体
-
首先在文件-build settings,将两个场景拖入到Build中的场景 SceneManager.LoadScene("SampleScene", LoadSceneMode.Additive);
- 第二个选项设置是同步加载还是异步加载。
- 第一个选项可以设置场景的下标,但一般不建议使用下标。
GameObject Cube = GameObject.Find("Sphere");
DontDestroyOnLoad(Cube);
设置某个场景的物体不会被消除 -
使用协程进行异步加载 void Start()
{
StartCoroutine(Load());
}
private IEnumerator Load()
{
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync("Scenes/SampleScene");
asyncOperation.allowSceneActivation = false;
while(asyncOperation.progress < 0.9f)
{
Debug.Log(asyncOperation.progress);
yield return null;
}
asyncOperation.allowSceneActivation = true;
if(asyncOperation.isDone)
{
Debug.Log("加载跳转完毕");
}
else
{
Debug.Log("加载没有跳转完毕");
}
}
- 可以认为协程是每一帧时会执行的语句,当yield return null;程序会临时返回一个结果,并等待下一帧时继续执行。
四、物体管理
- 标签和图层

标签和层级主要用于编程中搜索物体和过滤物体
-
预制件
-
创建
-
可以将场景中内容拖拽到资源中,保存成预制件,预制件一般只能保存一份。 -
预制件默认放在Resources文件夹下,可以通过API索引到预制件 //创建
GameObject go = Resources.Load<GameObject>("Object/Sphere");
GameObject.Instantiate(go);
-
如果没有放在Resources文件夹下,可通过public 变量传入预制件。 -
使用脚本对物体交互 //创建
//GameObject go = Resources.Load<GameObject>("Object/Sphere");
//GameObject.Instantiate(go);
查找,如果要查找子物体,可以使用/寻找到子物体。
//GameObject go1 = GameObject.Find("Sphere");
//go1.SetActive(false);
//查找(按照标签查找)
GameObject go2 = GameObject.FindGameObjectWithTag("Hero");
//go2.SetActive(false);
go2.name = "Cube02";
//go2.transform.position = Vector3.zero;
go2.transform.position = new Vector3(0, 0, 0);
//go2.transform.rotation = Quaternion.Euler(0, 90, 90);
go2.transform.eulerAngles = new Vector3(0, 90, 90);
//销毁
Destroy(go2);
五、组件管理
-
查找组件
- GetComponent(s)<>:查找当前组件
- GetComponent(s)InChildren<>:查找组件自己和子元素
- GetComponent(s)InParent<>:查找组件自己和父元素
GameObject go = GameObject.Find("Text");
go.GetComponentInChildren<Text>().text = "查找到组件";
-
禁用组件
- 组件中包含enable属性,可以用来关闭组件
- 使用Destory可以删除组件
六、UGUI图形系统
-
画布与事件系统
- 画布的渲染空间
- 屏幕空间-覆盖:看不到其他物体
- 屏幕空间-摄像机:可以看到在Canvas前面的3D物体
- 世界空间:Canvas本身可以移动到相机视线之外
- UI缩放模式
- 恒定像素大小
- 屏幕大小缩放:一般选择此模式,分为宽度匹配和高度匹配
- 恒定物理大小
- EventSystem
- 必须存在
- 在运行的时候可以看到事件系统的基本信息
-
文本
-
输入框
- 内容类型:文本、密码
- 输入框自己包含两个子物体:占位符和真实文本
-
首先先自己尝试按照流程创建用户界面

并实现三个需求:
- 点击登录,在控制台输出账号和密码
- 替换背景图片
- 点击官网,跳转到指定URL
InputField userInput;
InputField pwdInput;
Button loginBtn;
public Sprite bg;
// Start is called before the first frame update
void Start()
{
userInput = transform.Find("EditAccount").GetComponent<InputField>();
pwdInput = transform.Find("EditPassword").GetComponent<InputField>();
loginBtn = transform.Find("Login").GetComponent<Button>();
loginBtn.onClick.AddListener(LoginBtnOnClick);
//替换背景图片
transform.Find("BG").GetComponent<Image>().sprite = bg;
//打开网页
transform.Find("website").GetComponent<Button>()
.onClick.AddListener(WebSiteOnClick);
}
void LoginBtnOnClick()
{
string account = userInput.text;
string pwd = userInput.text;
Debug.Log("Account:" + account);
Debug.Log("Password:" + pwd);
}
void WebSiteOnClick()
{
Application.OpenURL("http://www.baidu.com");
}
在编程的时候,注意:
- Find找到的控件只能包含孩子结点,不能包含孙子结点。
- 所有本身的对象为Transform,可以用transform获取到自身的对象。
- 不同组件拥有不同的能力,主要原因在于添加了不同的组件,需要找到合适的组件,才能修改其名字。
- 组件添加事件使用的是.OnXXX.AddXXXListener()
- 跳转到指定URL使用的函数是Application.OpenURL
-
Toggle
- 包含选择框和文本两个子控件,可以自由调节
- 包含IsOn属性,判断是否打钩
- 如果需要使用开关组,需要在“开关组”的选项中选择一个包含了开关组(ToggleGroup)的组件
-
滑动条
- 获取滑动条的值从属性value中获取
- 获取滑动条发生改变的事件是 onValueChanged
-
滚动视图
-
在UI中选择滚动视图,滚动视图中包含content是用来包含其他元素的容器,content的大小就是页面的大小。 -
可以选择水平Layout、垂直Layout、Grid Layout来对内容进行自动化的排序。 -
可以使用内容尺寸适配器(Content Size Fitter),内容尺寸适配器在垂直方向或水平方向可以根据内容自动跳转父元素的大小,设置Preferred Size,有时候对于文本也可以对根据内容做自适应。 -
滚动视图中包含一个Viewport,是使用遮罩的方法将其它的元素不显示,对于创建圆形头像等可以使用遮罩的方法。 -
GameObject用于预制件,Transform用于场景中任何物体的使用。 public GameObject Hero;
public Transform Content;
void Start()
{
}
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.A))
{
GameObject _hero = GameObject.Instantiate(Hero);
_hero.transform.SetParent(Content);
}
}
-
可以自定义类似于滑动条的组件
-
创建父子两个Image -
给子Image添加任意一个原图像(实际测试发现对于半透明图像不可用) -
设置好父子物体的颜色,选择图像类型为“已填充”,填充方法为水平。 -
通过代码修改填充总数,可以实现将子控件填充到对应百分比的位置。

-
其他常用组件
- Outline:增加边框
- Shadow:添加阴影
七、用户输入管理
-
虚拟轴 通过Input.GetAxis获取轴的值。 float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
if(h != 0)
{
//transform.position = new Vector3(
// h + transform.position.x,
// transform.position.y,
// transform.position.z
// );
transform.eulerAngles = new Vector3(
h + transform.eulerAngles.x,
transform.eulerAngles.y,
transform.eulerAngles.z
);
}
if(v != 0)
{
//transform.position = new Vector3(
// transform.position.x,
// transform.position.y,
// v + transform.position.z
//);
}
-
获取键盘事件
- 通过GetKey、GetKeyDown、GetKeyUp来获取键盘的按下状态。
- GetKey是每一帧都能获取按下状态,GetKeyDown和GetKeyUp只获取一次。
-
获取鼠标事件
- 通过Input.GetMousrButton、GetMouseButtonDown、GetMouseButtonUp来获取。
- 传入的值0表示鼠标左键,1为鼠标右键。
-
移动设备输入
- Input.touchCount获取有多少手指碰到了。
- Input.touches获取每一根手指的状态,finggerid是手指id、position为位置,deltaPosition是和上次相比移动的距离。
八、自然环境设计
- 天空盒的创建
- 一般使用6张图片创建天空盒或Cubemap创建天空盒。
- 首先创建一个材质,选择天空盒,将6张图片设置好,就可以将天空盒拖拽到场景中了。
- Cubemap全景图的后缀是hdr,导入后需要将纹理形状改成立方体,同样可以设置天空盒。
- 山脉和地表贴图的创建
- 可以在Unity Assert Store下载Terrain Tools XXX资源包去尝试使用。
- 在实际项目中,一般是公司的地模制作,该部分不做重点学习。
- 树和草的创建
- 水和雾
九、光照系统
-
灯光组件

-
照明设置
-
可以在照明设置环境光以及天空盒 -
可以选择混合模式,是否开启烘焙照明 -
可以选择光照贴图是CPU还是GPU -
可以设置雾,当雾的密度调大时,会有浓雾的效果。 -
可以设置光晕:需要在光源处选择绘制光晕

-
可以设置炫光
- 首先创建炫光,设置纹理和纹理布局(一般是一维)
- 将创建的炫光赋值到指定的光源
-
自发光
- 自发光使用自发光材质实现,创建新的材质,选择发射。
- 可以选择一个发光贴图,以及选择发光颜色,强度。最终赋值给自发光物体即可。
- 自发光需要物体必须是静态的,也只能烘焙静态的物体。
-
光照探测器
- 光照探测器相当于记录了不同点的光照信息,从而可以实时动态的获取一些需要烘焙的光源的光照。
- 光照探测器用于渲染非静态物体。
- 建议多创建一些光照探测器。
-
反射探测器
- 反射探测器主要用于非常镜面的物体,例如光滑的地板
- 必须要求反射的物体具有镜面反射效果,相互配合才能看到反射探测器的效果。
十、3D模型管理
-
蒙皮网格与普通网格的对比
- 蒙皮网格主要是用于人物,放在人物在动画中材质被不正常拉伸。
-
材质的使用
-
换肤功能的实现
十一、物理系统
-
3D物理系统
-
2D物理系统
-
2D刚体和碰撞器
- 一般在Canvas中创建Image或RawImage(区别:Image要比RawImage更加强大,Image主要处理图片类型,RawImage主要用于纹理类型的)
- 在创建碰撞器的时候,需要指定大小,一般需要手动指定大小和2D物体大小一致。
-
2D表面效果器
- 用于设置2D物体在表面的初始速度、力
- 必须在碰撞器上勾选:由效果器使用
-
2D区域效果器
- 在区域内施加的力
- 需要勾选:是触发器、由效果器使用
-
2D浮力效果器
- 在区域内收到浮力影响
-
2D点效果器
- 在区域内受到引力或斥力
十二、动画系统
-
动画启动播放控制
-
使用按键控制动画播放
-
创建动画器控制器 -
将一些动画拖入到动画器控制器中 -
在动画器选项卡中添加参数id,类型为int -
设置动画器控制器的进入不同状态的条件 -
在模型上添加动画器,设置好动画器控制器和Avatar -
编写脚本,控制动画器的值 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);
}
}
-
选择跳转条件,取消对“可以过度到自己”的勾选。 -
如果希望动画可以循环,选择动画,勾选循环时间。 -
如果希望无延迟的切换到其它的动画,可以取消“有退出时间” -
人形动画
- 尝试使用其它人物角色的动画(实际操作)
- 在检查器中可以看到人形动画的骨骼(实际操作)
-
动画遮罩
- 了解对于非人物角色和人物角色动画遮罩的过程。(实际操作)
- 对于非人物遮罩,使用的是转换,指定具体的Avator,取消勾选一些不需要遮罩的骨骼。
- 在层总指定具体的遮罩。
- 可以创建不同的层,然后使用不同的动画遮罩,实现动作的混合。
-
动画事件
- 动画事件是在界面中添加的,播放指定的动画,在指定的帧处添加事件的响应函数。(实际操作)
十三、寻路系统
-
制作一个点击自动寻路程序
-
先搭建一个场景 -
将场景中的物体设置为导航静态(在检查器-静态下拉菜单中设置) -
打开烘焙窗口:窗口-ai-烘焙 -
切换到烘焙选项卡,进行烘焙,如果模型非常的小,需要设置好半径等参数才能看到烘焙的结果。 -
向人物增加组件——导航网格代理 -
添加脚本 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);
}
}
}
-
重要属性
- 代理半径、代理高度等
- 区域和成本:在区域内有一个设置成本的按钮,一般导航选择成本最低的路线。可以在对象中选择某一段路导航区域的类型,然后重新进行烘焙。
- 生成分离网格连接可以设置从高处跳跃的最大高度和最远距离。
- 必须在对象选项卡中勾选 生成网格连接(Generate OffMeshLinks),才能生成连接
-
动态障碍物
- 可以使用导航网格障碍禁止两个地方的导航连接
- 实际测试导航障碍不会改变导航路径的计算结果,只会阻碍物体的前进,如果代理半径过小,可能会造成导航物钻死胡同的现象。
-
分离网格跳跃线
- 首先在模型上创建分离网格连接组件,添加两个Transform,拖入到场景中。
- 修改导航设置,在对象选项卡中勾选 生成网格连接(Generate OffMeshLinks)
- 最后重新烘焙,就可以实现分离网格的连接。
-
运行时动态烘焙网格
-
使用官方扩展工具 NavMeshComponents工具(https://github.com/Unity-Technologies/NavMeshComponents)将NavMeshComponents/Assets/NavMeshComponents复制到项目中使用。 -
在需要导航的物体上创建 Nav Mesh Surface组件 并进行烘焙。 -
实现在点击的位置创建立方体 public GameObject buildPrefab;
NavMeshSurface surface;
void Start()
{
surface = GetComponent<NavMeshSurface>();
}
void Update()
{
if(Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
bool isCollider = Physics.Raycast(ray, out hit);
if(isCollider)
{
GameObject go = Instantiate(buildPrefab, hit.point, Quaternion.identity);
go.transform.SetParent(this.transform);
surface.BuildNavMesh();
}
}
}
十四、音效系统
-
音频源组件和音频监听器组件
- 一个场景中只能有一个监听器,一般相机上默认有一个音频监听器
- 常用属性:静音、循环、音量
-
音频源组件常用函数 AudioSource audio;
void Start()
{
audio = transform.GetComponent<AudioSource>();
audio.clip = Resources.Load<AudioClip>("bj4");
}
void Update()
{
if(Input.GetKeyDown(KeyCode.A))
{
audio.Play();
//audio.Pause();
//audio.Stop();
}
}
-
音频过滤器和音频混响区(不常用,了解)
- 常用的过滤器
- 音频低通过滤器
- 音频高通过滤器
- 音频合成过滤器
- 音频失真过滤器
- 音频回声过滤器
- 音频混响过滤器
- 常用参数
- 最小距离
- 最大距离
- 音频管理器
- 全局音量
- 音频衰减因子
- DSP缓存区,缓存大小
十五、特效系统
-
粒子系统
-
使用资源包中的粒子(实践) -
使用代码编辑粒子系统 GameObject partivalGo;
ParticleSystem particleSystem;
void Start()
{
partivalGo = GameObject.Instantiate(Resources.Load<GameObject>("22_RFX_Fire_Campfire1"));
partivalGo.transform.position = transform.position;
particleSystem = partivalGo.GetComponent<ParticleSystem>();
//修改属性
ParticleSystem.MainModule mainModule = particleSystem.main;
mainModule.loop = true;
//播放,暂停,停止
particleSystem.Play();
//particleSystem.Stop();
//particleSystem.Pause();
}
-
粒子触发回调
- 在粒子系统上选择触发器,可以设置进入、退出等是忽略、杀掉还是回调。
- 必须指定触发的检测对象。
ParticleSystem particle;
void Start()
{
particle = transform.GetComponent<ParticleSystem>();
}
private void OnParticleTrigger()
{
List<ParticleSystem.Particle> particles = new List<ParticleSystem.Particle>();
//这个地方并没有获取到任何的粒子?
int num = particle.GetTriggerParticles(
ParticleSystemTriggerEventType.Enter,
particles);
for (int i=0;i< num;i++)
{
ParticleSystem.Particle par = particles[i];
par.startColor = Color.red;
particles[i] = par;
}
}
- 通过OnParticleTrigger了解到碰撞的粒子,以及GetTriggerParticles获取碰撞的粒子对象。
-
拖尾
- 将拖尾的粒子对象一般设置到人物或道具在子物体上,当物体发生移动时,会产生拖尾
- 拖尾使用的拖尾渲染器来实现
- 所有的可见物体都是通过渲染器来实现。
- Unity3D底层使用的是C++开发,通过提供一个个插件实现物体的渲染。
- 参考Low-level native plugin,使用OpenGL或DirectX开发渲染插件。
- 拖尾使用emit属性发射拖尾或停止拖尾。
-
粒子立场
- 在场景中添加粒子立场。
- 粒子系统需要勾选外力。
- 修改粒子立场的外力大小。
十六、视频播放管理
- 视频播放器组件
- 视频组件常用函数
- VideoPlayer.Play()/Pause()/Stop()/isPlaying()/url/clip
|