《海島奇兵》是由芬蘭Supercell Oy公司開發(fā),Supercell Oy及昆侖游戲發(fā)行的一款戰(zhàn)斗策略類掂之、全球同服的手機(jī)游戲蕊梧。估計(jì)大部分人都玩過,即使沒有玩過也應(yīng)該知道這款游戲吧球拦。本人之前就熱衷于這款游戲,對(duì)于熱愛游戲開發(fā)的我來說,看見這款游戲的效果坎炼,實(shí)在是嘆為觀止愧膀,甚至想把所有的效果都模擬過來放入自己的游戲中。這不点弯,現(xiàn)在就來用Unity模擬它收獲資源產(chǎn)生大量資源圖標(biāo)飛入到背包的效果扇调。
我就取名為WeiButEffect
C#腳本矿咕,主要就是這個(gè)類實(shí)現(xiàn)的所有功能抢肛,先上源碼。
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 模擬《海島奇兵》收獲資源的爆炸效果
/// weibut.com
/// </summary>
public class WeiButEffect : MonoBehaviour {
/// <summary>
/// 移動(dòng)到的目標(biāo)
/// </summary>
public Transform target;
/// <summary>
/// 運(yùn)動(dòng)時(shí)間
/// </summary>
public float factor = 1f;
/// <summary>
/// 生成個(gè)數(shù)
/// </summary>
public int amount;
/// <summary>
/// 需要生成的物體
/// </summary>
public Transform prefab;
/// <summary>
/// 爆炸范圍
/// </summary>
public float explosionRadius = 200;
public System.Action onFinish;//完成后回調(diào)
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">創(chuàng)建在哪</param>
/// <param name="target">移動(dòng)到哪</param>
/// <param name="prefab">移動(dòng)物體</param>
/// <param name="amount">個(gè)數(shù)</param>
/// <param name="explosionRadius">擴(kuò)散范圍</param>
/// <param name="onFinish">移動(dòng)完成回調(diào)</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的擴(kuò)展
/// </summary>
public static class TRE
{
/// <summary>
/// 獲取Canvas里transform的屏幕坐標(biāo)
/// </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;
}
}
代碼這么多碳柱,其實(shí)很簡(jiǎn)單捡絮,就只調(diào)用CreateEffect
靜態(tài)函數(shù)就可以了,參數(shù)的意思也都有注釋莲镣。還有一個(gè)靜態(tài)類TRE
福稳,主要是transform的擴(kuò)展。
可以這樣
也可以這樣
甚至還可以這樣
當(dāng)然你想怎樣就怎樣H鹞辍5脑病!
這個(gè)版本是無音效版的半火,如果需要請(qǐng)自行擴(kuò)展越妈。