植物大战僵尸 - 阳光生成抛物线运动分析
下面是植物大战僵尸开发过程遇到的阳光以抛物线的形式生成的问题,查阅相关资料,下面是实现方法
代码实现
阳光的抛物线运动主要通过以下两个脚本实现:
1. SunFlower.cs - 向日葵生成阳光
csharp
public void OnGrowing()
{
// 在向日葵位置实例化一个阳光预制体
GameObject sun = Instantiate(sunPrefab, transform.position, Quaternion.identity);
// 随机生成一个距离值(0.5到1.5之间)
float distance = Random.Range(0.5f, 1.5f);
// 随机决定距离是正值还是负值,决定阳光往左还是往右移动
distance = Random.Range(0, 2) == 0 ? distance : -distance;
// 计算目标位置,在x轴上偏移随机距离
Vector3 postion = transform.position;
postion.x += distance;
// 调用阳光对象的JumpToTarget方法,开始抛物线运动
sun.GetComponent<Sun>().JumpToTarget(postion);
}
2. Sun.cs - 阳光抛物线运动
csharp
public void JumpToTarget(Vector3 target)
{
// 计算起点和终点的中点位置
Vector3 centerPos = (transform.position + target) / 2;
// 计算起点和终点的距离
float distance = Vector3.Distance(transform.position, target);
// 将中点的y坐标抬高,高度为距离的一半,形成抛物线的顶点
centerPos.y += distance / 2;
// 使用DOTween插件实现路径动画
transform.DOPath(
new Vector3[] { transform.position, centerPos, target }, // 设置路径的三个关键点:起点、顶点、终点
moveDuration, // 运动持续时间
PathType.CatmullRom // 使用Catmull-Rom样条曲线插值
).SetEase(Ease.OutQuad); // 设置缓动效果为OutQuad
}
工作原理解析
-
阳光生成机制:
- 向日葵每隔一定时间(8秒)会生成一个阳光
- 生成时会随机决定阳光的落点,范围在向日葵左右0.5~1.5个单位距离内
-
抛物线运动实现:
- 使用三点确定抛物线:起点(生成位置)、顶点(中间高点)、终点(目标位置)
- 顶点的高度根据起点和终点的距离动态计算,为距离的一半
- 使用DOTween插件的DOPath方法实现平滑的路径动画
-
动画控制:
- 使用Catmull-Rom样条曲线实现平滑的路径插值
- OutQuad缓动效果使运动更自然,开始快而后逐渐减速
- 整个运动过程持续1秒
-
技术要点:
- 利用DOTween插件简化了复杂的运动轨迹实现
- 通过三点确定路径,而不是使用物理模拟,使得运动更可控
- 随机化的目标位置增加了游戏的趣味性和自然感
DOTween 插件使用指南
DOTween 是一个强大的 Unity 动画插件,它可以让你用简单的代码轻松实现任何游戏对象的移动、旋转、缩放、颜色变化、UI动画等平滑过渡效果,而无需手动编写复杂的动画逻辑。
- 易用性(简单的代码)
- 功能全面(任何游戏对象)
- 动画类型多样(移动、旋转等)
- 平滑性(过渡效果)
- 开发效率(无需手动编写复杂逻辑)
1. 基本设置
csharp
// 在项目开始时初始化(通常在游戏管理器中)
DOTween.SetTweensCapacity(500, 50); // 设置tween的容量
// 在使用前引入命名空间
using DG.Tweening;
2. 常见动画示例
移动物体 (Transform)
csharp
// 简单移动
transform.DOMove(new Vector3(5, 0, 0), 1f); // 在1秒内移动到指定位置
// 相对移动
transform.DOLocalMoveX(2f, 1f); // 在X轴相对移动2个单位
// 路径移动
Vector3[] path = new Vector3[]{
new Vector3(0, 0, 0),
new Vector3(1, 1, 0),
new Vector3(2, 0, 0)
};
transform.DOPath(path, 2f, PathType.Linear); // 2秒内沿路径移动
旋转 (Rotation)
csharp
// 旋转到指定角度
transform.DORotate(new Vector3(0, 180, 0), 1f); // 1秒内旋转到180度
// 持续旋转
transform.DORotate(new Vector3(0, 360, 0), 2f, RotateMode.FastBeyond360)
.SetLoops(-1, LoopType.Restart); // 无限循环旋转
缩放 (Scale)
csharp
// 统一缩放
transform.DOScale(2f, 1f); // 1秒内放大到2倍
// 分轴缩放
transform.DOScaleX(2f, 1f); // 只缩放X轴
UI动画
csharp
// 渐变透明度
image.DOFade(0f, 1f); // 1秒内淡出
// UI位置移动
rectTransform.DOAnchorPos(new Vector2(100, 100), 1f); // 移动UI元素
// 颜色变化
image.DOColor(Color.red, 1f); // 1秒内变为红色
3. 常用控制方法
csharp
Tween myTween = transform.DOMove(new Vector3(5, 0, 0), 2f);
// 设置延迟开始
myTween.SetDelay(1f);
// 设置缓动效果
myTween.SetEase(Ease.OutBounce);
// 设置循环
myTween.SetLoops(2, LoopType.Yoyo);
// 添加回调
myTween.OnComplete(() => Debug.Log("动画完成"));
myTween.OnStart(() => Debug.Log("动画开始"));
// 暂停和继续
myTween.Pause();
myTween.Play();
// 立即完成
myTween.Complete();
// 终止动画
myTween.Kill();
4. 常用缓动效果
Ease.Linear
: 线性运动Ease.InOutQuad
: 渐入渐出Ease.OutBounce
: 弹跳效果Ease.InBack
: 回退后前进Ease.OutElastic
: 弹性效果
5. 序列动画
csharp
// 创建动画序列
Sequence sequence = DOTween.Sequence();
// 添加多个动画
sequence.Append(transform.DOMove(new Vector3(2, 0, 0), 1f)) // 先移动
.Append(transform.DOScale(2f, 0.5f)) // 然后缩放
.Join(transform.DORotate(new Vector3(0, 180, 0), 0.5f)) // 同时旋转
.AppendInterval(0.5f) // 等待0.5秒
.Append(transform.DOMove(new Vector3(0, 0, 0), 1f)); // 最后返回
// 控制整个序列
sequence.SetLoops(2) // 重复两次
.SetEase(Ease.OutQuad) // 设置缓动
.Play(); // 开始播放
6. 性能优化建议
- 使用
SetAutoKill(false)
和对象池来重用Tween - 适当设置
DOTween.SetTweensCapacity()
避免运行时扩容 - 使用
SetLink()
将Tween与游戏对象关联,在对象销毁时自动销毁Tween - 及时使用
Kill()
清理不需要的Tween
以上示例展示了DOTween的基础用法,实际开发中可以根据需求组合使用这些功能来创建更复杂的动画效果。