AR互动大屏丨Add_自动循环动画、遮挡效果的实现

2024-08-14 16:54:06 浏览数 (1)

自动循环动画

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];
		}
	}
}

0 人点赞