美文网首页unityunity进阶教程合集Unity技术分享
Unity3D利用UGUI模拟《海岛奇兵》收获资源的爆炸效果

Unity3D利用UGUI模拟《海岛奇兵》收获资源的爆炸效果

作者: 微巴特 | 来源:发表于2017-08-09 11:06 被阅读99次

    《海岛奇兵》是由芬兰Supercell Oy公司开发,Supercell Oy及昆仑游戏发行的一款战斗策略类、全球同服的手机游戏。估计大部分人都玩过,即使没有玩过也应该知道这款游戏吧。本人之前就热衷于这款游戏,对于热爱游戏开发的我来说,看见这款游戏的效果,实在是叹为观止,甚至想把所有的效果都模拟过来放入自己的游戏中。这不,现在就来用Unity模拟它收获资源产生大量资源图标飞入到背包的效果

    204913367.png

    我就取名为WeiButEffectC#脚本,主要就是这个类实现的所有功能,先上源码。

    using System.Collections.Generic;
    using UnityEngine;
    /// <summary>
    /// 模拟《海岛奇兵》收获资源的爆炸效果
    /// weibut.com
    /// </summary>
    public class WeiButEffect : MonoBehaviour {
        /// <summary>
        /// 移动到的目标
        /// </summary>
        public Transform target;
        /// <summary>
        /// 运动时间
        /// </summary>
        public float factor = 1f;
        /// <summary>
        /// 生成个数
        /// </summary>
        public int amount;
        /// <summary>
        /// 需要生成的物体
        /// </summary>
        public Transform prefab;
        /// <summary>
        /// 爆炸范围
        /// </summary>
        public float explosionRadius = 200;
    
        public System.Action onFinish;//完成后回调
    
        float time0 = 0;
        List<Vector3> ctrlPoints = new List<Vector3>();
        List<Transform> particles = new List<Transform>();
    
        public void PlayEffect()
        {
            int n = Mathf.Max(1, amount);
            for (int i = 0; i < n; i++)
            {
                if (prefab)
                {
                    GenerateParticle(prefab);
                }
            }
    
            time0 = Time.time;
        }
    
        void GenerateParticle(Transform prefab)
        {
            var p = Instantiate(prefab, Vector3.zero, Quaternion.identity).gameObject;
            p.transform.SetParent(transform, false);
            particles.Add(p.transform);
            ctrlPoints.Add(Random.insideUnitSphere * explosionRadius);
        }
    
        // Update is called once per frame
        void Update () {
            if (!this.target)
            {
                OnFinish();
                return;
            }
            float t = (Time.time - time0) / Mathf.Max(0.1f, factor);
    
            if (t > 1)
            {
                t = 1;
    
                OnFinish();
            }
    
            Vector3 target = GetTargetPositionLocal();
    
            for (int i = 0; i < ctrlPoints.Count; i++)
            {
                Vector3 ctrl = ctrlPoints[i];
                Vector3 begin = Vector3.zero;
    
    
                Vector3 pos = Vector3.Lerp(Vector3.Lerp(begin, ctrl, t), Vector3.Lerp(ctrl, target, t), t);
    
                particles[i].localPosition = pos;
            }
        }
    
        void OnFinish()
        {
            Destroy(gameObject);
    
            if (onFinish != null)
            {
                onFinish();
            }
        }
    
        Vector3 GetTargetPositionLocal()
        {
            var screenPoint = target.GetScreenPoint();
    
            Vector2 localPoint = Vector2.zero;
            GetComponent<RectTransform>().ScreenPointToLocalPosition(screenPoint, out localPoint);
            return localPoint;
        }
    
    
        /// <summary>
        /// 模拟《海岛奇兵》收获资源的爆炸效果
        /// </summary>
        /// <param name="parent">创建在哪</param>
        /// <param name="target">移动到哪</param>
        /// <param name="prefab">移动物体</param>
        /// <param name="amount">个数</param>
        /// <param name="explosionRadius">扩散范围</param>
        /// <param name="onFinish">移动完成回调</param>
        /// <returns></returns>
        public static WeiButEffect CreateEffect(Transform parent, Transform target, Transform prefab, int amount, float explosionRadius = 200, System.Action onFinish = null)
        {
            GameObject instance = new GameObject(prefab.name);
            instance.transform.SetParent(parent, false);
            instance.AddComponent<RectTransform>();
            var effect = instance.AddComponent<WeiButEffect>();
            effect.prefab = prefab;
            effect.amount = amount;
            effect.target = target;
            effect.onFinish = onFinish;
            effect.explosionRadius = explosionRadius;
            effect.PlayEffect();
            return effect;
        }
    }
    
    
    /// <summary>
    /// TransForm的扩展
    /// </summary>
    public static class TRE
    {
        /// <summary>
        /// 获取Canvas里transform的屏幕坐标
        /// </summary>
        /// <param name="trans"></param>
        /// <returns></returns>
        public static Vector3 GetScreenPoint(this Transform trans)
        {
            var canvas = trans.GetComponentInParent<Canvas>();
            if (canvas)
            {
                var uiCamera = canvas.worldCamera ?? Camera.main;
                if (canvas.renderMode == RenderMode.WorldSpace)
                {
                    uiCamera.WorldToScreenPoint(trans.position);
                }
                else if (uiCamera && canvas.renderMode != RenderMode.ScreenSpaceOverlay)
                {
                    return uiCamera.WorldToScreenPoint(trans.position);
                }
                else
                {
                    return trans.position;
                }
            }
            return Camera.main.WorldToScreenPoint(trans.position);
        }
    
        public static bool ScreenPointToLocalPosition(this RectTransform rect, Vector2 screenPoint, out Vector2 localPoint)
        {
            if (rect)
            {
                Transform current = rect;
                Canvas canvas = null;
                for (; current != null; current = current.parent)
                {
                    canvas = current.GetComponent<Canvas>();
                    if (canvas != null)
                    {
                        break;
                    }
                }
    
                var cam = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : (canvas.renderMode == RenderMode.ScreenSpaceCamera ? canvas.worldCamera : canvas.worldCamera ?? Camera.main);
                return RectTransformUtility.ScreenPointToLocalPointInRectangle(rect.parent.GetComponent<RectTransform>(), screenPoint, cam, out localPoint);
            }
            localPoint = Vector2.zero;
            return false;
        }
    }
    

    代码这么多,其实很简单,就只调用CreateEffect静态函数就可以了,参数的意思也都有注释。还有一个静态类TRE,主要是transform的扩展。

    可以这样

    1.gif

    也可以这样

    2.gif

    甚至还可以这样

    3.gif

    当然你想怎样就怎样!!!

    这个版本是无音效版的,如果需要请自行扩展。

    相关文章

      网友评论

      • 雨落随风:我也挺喜欢海岛奇兵,顶级了都~
        微巴特:@雨落随风 坐标转换一下就可以了,:smiley:
        雨落随风:@雨落随风 游戏里面还有这几个细节,1,资源爆出点是对应是3D世界物体,2,他是近乎一个一个陆续发放到仓库,3,资源会分门别类的发放到指定的仓库

      本文标题:Unity3D利用UGUI模拟《海岛奇兵》收获资源的爆炸效果

      本文链接:https://www.haomeiwen.com/subject/yepfrxtx.html