一、简单的爆炸
- 使用场景
零部件的简单爆炸展示 - 复杂爆炸,比如物体炸开后,破碎的物体沿曲线运动,而且有动力学效果,则需要更复杂的实现,本例不作讨论。
二、实现的过程
- 1、爆炸过程
从初始位置 移动到 结束位置(position和ratation做lerp插值运动) - 2、收拢过程
从结束位置 移动到 初始位置(position和ratation做lerp插值运动)
中间所有的物体都是在两点之间做匀速直线运动
- 3、爆炸前和爆炸后的方位信息记录
物体方位信息表
自定义的类-【物体和方位信息】
/// <summary>
/// 物体和方位信息
/// 各个部件,在爆炸前和爆炸后的位置和方向信息
/// </summary>
[Serializable]
public class goPositions{
[Header("物体")]
[SerializeField]
public GameObject go;
[Header("爆炸前的位置")]
[SerializeField]
public Vector3 positionStart;
[Header("爆炸前的方向")]
[SerializeField]
public Quaternion rotationStart;
[Header("爆炸后的位置")]
[SerializeField]
public Vector3 positionEnd;
[Header("爆炸后的方向")]
[SerializeField]
public Quaternion rotationEnd;
}
- 4、爆炸的过程——插值或者pingpong
// Update is called once per frame
void Update()
{
//测试代码==================================begin
//if (Input.GetKeyDown(KeyCode.Alpha1))
//{
// Debug.Log("111");
// SetToStartTransform();
//}
//if (Input.GetKeyDown(KeyCode.Alpha2))
//{
// Debug.Log("222");
// SetToEndTransform();
//}
//测试代码==================================end
//更新物体的位置和方向——pingpong效果
stepValue = Mathf.PingPong(Time.time, time) / time;
GoPositions.ForEach(x =>
{
x.go.transform.position = Vector3.Lerp(x.positionStart, x.positionEnd, stepValue);
x.go.transform.rotation = Quaternion.Lerp(x.rotationStart, x.rotationEnd, stepValue);
});
}
三、代码清单
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;
/// <summary>
/// 一个组合的物体爆炸和收拢
/// 爆炸:从初始位置 移动到 结束位置(position和ratation做lerp插值运动)
/// 收拢:从结束位置 移动到 初始位置(position和ratation做lerp插值运动)
///
/// 编辑器状态下的功能:
/// 没有爆炸前: 右键菜单《初始化【部件和开始方位】》,记录各个部件的原始方向和位置
/// 拖拽爆炸位置后:右键菜单《初始化【结束方位】》 ,记录各个部件的结束方向和位置
///
/// 说明:物体命名规则,凡是爆炸的物体(要炸开和合拢的物体),命名包含"部件"两字
/// </summary>
public class baozha : MonoBehaviour
{
/// <summary>
/// 物体和方位信息
/// 各个部件,在爆炸前和爆炸后的位置和方向信息
/// </summary>
[Serializable]
public class goPositions{
[Header("物体")]
[SerializeField]
public GameObject go;
[Header("爆炸前的位置")]
[SerializeField]
public Vector3 positionStart;
[Header("爆炸前的方向")]
[SerializeField]
public Quaternion rotationStart;
[Header("爆炸后的位置")]
[SerializeField]
public Vector3 positionEnd;
[Header("爆炸后的方向")]
[SerializeField]
public Quaternion rotationEnd;
}
[Header("部件的根物体")]
[SerializeField]
public GameObject root;
[Header("部件以及方位信息列表")]
[SerializeField]
public List<goPositions> GoPositions = new List<goPositions>();
[Header("散开的时间")]
[SerializeField]
public float time;
/// <summary>
/// pingpong效果的进度条值
/// </summary>
private float stepValue;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
//测试代码==================================begin
//if (Input.GetKeyDown(KeyCode.Alpha1))
//{
// Debug.Log("111");
// SetToStartTransform();
//}
//if (Input.GetKeyDown(KeyCode.Alpha2))
//{
// Debug.Log("222");
// SetToEndTransform();
//}
//测试代码==================================end
//更新物体的位置和方向——pingpong效果
stepValue = Mathf.PingPong(Time.time, time) / time;
GoPositions.ForEach(x =>
{
x.go.transform.position = Vector3.Lerp(x.positionStart, x.positionEnd, stepValue);
x.go.transform.rotation = Quaternion.Lerp(x.rotationStart, x.rotationEnd, stepValue);
});
}
/// <summary>
/// 物体摆放到初始位置
/// </summary>
void SetToStartTransform()
{
GoPositions.ForEach(
x=>
{
x.go.transform.position = x.positionStart;
x.go.transform.rotation = x.rotationStart;
});
}
void SetToEndTransform()
{
GoPositions.ForEach(
x =>
{
x.go.transform.position = x.positionEnd;
x.go.transform.rotation = x.rotationEnd;
});
}
#if UNITY_EDITOR // Editor的非running状态使用
[ContextMenu("记录【部件和开始方位】")]
#endif
public void InitTransformStart()
{
GoPositions.Clear();
root.transform.GetComponentInChildren<Transform>().Cast<Transform>().ToList()
.ForEach(item =>
{
if (item.name.Contains("部件")) //
{
goPositions gp = new goPositions();
gp.go = item.gameObject;
gp.positionStart = item.gameObject.transform.position;
gp.rotationStart = item.gameObject.transform.rotation;
GoPositions.Add(gp);
}
else
{
//
}
});
Debug.Log("初始方位记录完毕");
}
#if UNITY_EDITOR // Editor的非running状态使用
[ContextMenu("记录【结束方位】")]
#endif
public void InitTransformEnd()
{
var allGos = root.transform.GetComponentInChildren<Transform>().Cast<Transform>().ToList();
GoPositions.ForEach(x=>
{
x.positionEnd = allGos.Where(go => go.gameObject.name == x.go.name).ToList()[0].position;
x.rotationEnd = allGos.Where(go => go.gameObject.name == x.go.name).ToList()[0].rotation;
});
Debug.Log("结束方位记录完毕");
}
}