自动循环动画
1、铺设路点
创建N个路点,创建Gizmos文件夹,并放入格式为png的Point文件名图片,在每个路点增加脚本如下
代码语言:javascript复制using UnityEngine;
public class PathNode : MonoBehaviour {
public PathNode P_Paretn;
public PathNode P_Next;
public void SetNext(PathNode node) {
if (P_Next != null) {
P_Next.P_Paretn = null;
P_Next = node;
node.P_Paretn = this;
}
}
void OnDrawGizmos()
{
Gizmos.DrawIcon(this.transform.position, "Point.png");
}
}
P_Paretn为父路点,P_Next为下一个路点。没有则不需要拖入
2、重写控制恐龙运动动画的代码
代码语言:javascript复制using UnityEngine;
public class Din_Auto : MonoBehaviour {
public PathNode m_currentNode=null;
public float speed = 20.0f;
//储存走路时间
public Din_Auto inst;
public Animator V_Ani;
public bool Move_Bl = true;
//控制恐龙是否行走
// Use this for initialization
void Start () {
inst = this;
m_currentNode = GameObject.Find("P_A_01").GetComponent<PathNode>();
Invoke("Eating", 1.8f);
//让恐龙经过1.8秒后吃东西
Invoke("Moving", 8.8f);
//让恐龙经过8.8秒(吃东西动作播放完)后继续走路
}
void Update () {
if (Move_Bl)
{
RotateTo();
MoveTo();
}
}
//让恐龙执行吃东西动画的函数
public void Eating() {
Move_Bl = false;
V_Ani.SetTrigger("Eating");
}
public void Moving() {
Move_Bl =true;
V_Ani.SetTrigger("Moving");
}
public void RotateTo() {
float current = transform.eulerAngles.y;
this.transform.LookAt(m_currentNode.transform);
Vector3 target = transform.eulerAngles;
float next = Mathf.MoveTowardsAngle(current,target.y,20*Time.deltaTime);
this.transform.eulerAngles = new Vector3(0,next,0);
}
public void MoveTo() {
Vector3 pos1 = transform.position;
Vector3 pos2 = m_currentNode.transform.position;
float dist = Vector2.Distance(new Vector2(pos1.x,pos1.z),new Vector2(pos2.x,pos2.z));
if (dist<2f) {
if (m_currentNode.P_Next == null)
{
Destroy(gameObject);
}
else {
m_currentNode = m_currentNode.P_Next;
}
}
transform.Translate(new Vector3(0, 0, speed * Time.deltaTime));
}
}
a、通过上面代码,可以看出RotateTo()方法里的Mathf.MoveTowardsAngle(current,target.speed)控制两个路点之间的转向
代码语言:javascript复制float next = Mathf.MoveTowardsAngle(current,target.y,20*Time.deltaTime);
它规定了起始角度,终止角度和转弯速度。很明显,第一和第二个路点之间,是没有转向的。在经过第二个路点,转向第三个路点时,模型角度才会随时间发生变化
b、MoveTo()里面的Translate()控制了模型的位移增量
当然也有更精确的控制策略,比如计算出两点之间运动距离所需时间,平均分配转弯角度,或者更写实的在路点一定距离内,进行转弯
c、MoveTo()实现了下个路点的切换,以及是否为最后一个路点的判断
3、生成恐龙
将该代码附在第一个路点上,每过N秒,生成一个新的恐龙
更精确控制策略可自行尝试
代码语言:javascript复制using UnityEngine;
public class Ins_Din : MonoBehaviour {
public GameObject Din_Pre;
private int Frame_Count;
//生成恐龙
void FixedUpdate() {
Frame_Count ;
if (Frame_Count>1000) {
Ins();
Frame_Count = 0;
}
}
void Ins() {
Instantiate(Din_Pre, gameObject.transform.position, gameObject.transform.rotation);
}
}
遮挡效果实现
该效果使用了一个shader“Mask”(附录1)和一个脚本“SetRenderQueue”(附录2),两者配合完成了效果的实现
a、shader添加到材质球上,材质球赋予遮挡恐龙的物体模型,完成遮挡
b、脚本添加至恐龙Perfab的Raptor层
附录1
shader:Mask
代码语言:javascript复制Shader "Masked/Mask" {
SubShader {
// Render the mask after regular geometry, but before masked geometry and
// transparent things.
Tags {"Queue" = "Geometry 10" }
// Don't draw in the RGBA channels; just the depth buffer
ColorMask 0
ZWrite On
// Do nothing specific in the pass:
Pass {}
}
}
附录2
SetRenderQueue
代码语言:javascript复制/*
SetRenderQueue.cs
Sets the RenderQueue of an object's materials on Awake. This will instance
the materials, so the script won't interfere with other renderers that
reference the same materials.
*/
using UnityEngine;
[AddComponentMenu("Rendering/SetRenderQueue")]
public class SetRenderQueue : MonoBehaviour {
[SerializeField]
protected int[] m_queues = new int[]{3000};
protected void Awake() {
Material[] materials = GetComponent<Renderer>().materials;
for (int i = 0; i < materials.Length && i < m_queues.Length; i) {
materials[i].renderQueue = m_queues[i];
}
}
}