【推荐100个unity插件之17】具有可破坏/砍倒unity地形树木能力的破坏系统,实现unity砍树效果 —— DestroyIt - Destruction System
unity破坏系统插件之前其实已经推荐过了几个,但是他们不具备砍树树的能力(其实是不适合)。你是否一直有个疑问?unity地形刷的树要如何砍伐破坏呢?今天推荐的这个插件DestroyIt - Destruction System,现在版本 1.10 具有创建可破坏地形树木的能力了!使用 Unity 的地形系统来放置树木,然后再用 DestroyIt 来让它们变得完全可破坏。DestroyIt 是一
最终效果
文章目录
前言
unity破坏系统插件之前其实已经推荐过了几个,但是他们不具备砍树树的能力(其实是不适合)。
【推荐100个unity插件之13】推荐一款开源的Unity网格破碎插件,实现在Unity中展示可破坏的墙壁的——unity-fracture
【推荐100个unity插件之4】OpenFracture插件实现unity3d物体破裂和切割
【推荐100个unity插件之3】切割unity3d物体插件——Ezy-Slice的使用
你是否一直有个疑问?unity地形刷的树要如何砍伐破坏呢?
今天推荐的这个插件DestroyIt - Destruction System,现在版本 1.10 具有创建可破坏地形树木的能力了!使用 Unity 的地形系统来放置树木,然后再用 DestroyIt 来让它们变得完全可破坏。
DestroyIt 是一款高度优化的破坏系统,它为你的游戏提供了伤害处理、修复和破坏对象等选项。
利用标准着色器和可自定义的伤害纹理,对象可以显示可见的渐进伤害(甚至可以修复)。你也可以以任何伤害阶段下播放伤害特效,举个例子,一个引擎会在半血量状态下开始熏烟,而在四分之一血的状况下会着火。
从播放粒子特效到用预制件替换对象,破坏可以是简单的或逼真的。你甚至可以将这两个方法结合在一起来获得更奢侈的效果。
DestroyIt 是设计来高效地处理大规模毁灭的。该框架提供了用于限制粒子特效和碎片的工具,因为许多对象会一次性被摧毁,或者会离镜头更远。对象池化也用了来优化内存分配。
下载
https://assetstore.unity.com/packages/tools/physics/destroyit-destruction-system-18811#description
可破坏的地形树
新建地形
关闭树碰撞器
破坏的树预制体
随便导入一个树模型
只留下树干添加碰撞体,最好是使用胶囊体的碰撞体,因为底下是圆的,这样能让树很好的倒下
调节树的碰撞体不要深入地下
,不然树可能会被弹飞
树添加刚体配置,冻结刚体Y轴,防止他倒地后在地面滚动
制成破坏预制件
制作可破坏树的原始版本
重新拖入一个新的树模型
给树添加Destructible组件,生命值设置为200
绑定被破坏的预制体,就是我们前面的配置好的
可以在树干上添加命中效果,添加Hit Effects脚本,选择命中特效WoodBulletHit
保存为预制件,为了做区分可以改个名字
在地形上添加树
快速添加第一人称控制器
设置-可破坏的树
会弹出提示
翻译一下就是:
关于可破坏树的说明
注意:为了使用可破坏的树木,你需要在地形上
取消启用树碰撞器
。一旦你将树添加到地形中,点击TreeManager上的“Update
Trees”按钮,DestroyIt将创建带有碰撞器的游戏对象,并将它们放置在地形树实例上,这样它们就可以被摧毁了。
取消地形启用树碰撞器我们已经设置好了,接下来需要在DestroyIt找到TreeManager组件点击Update Trees按钮
运行效果
ps:这里破坏树的预制体和原树的预制体之间碰撞器配置不太好,如果碰撞器的位置一致且不会在地下,那么效果肯定会更好,实现真正意义上的无缝衔接
攻击具体是如何实现的呢(补充)
如果你想自己创建人物控制器,可能就需要用到,当然通常我们不会用它自带的人物控制脚本
其实就是在人物身上挂载个攻击区域检测脚本
点击攻击时调用里面的方法(当然还包括修复的方法),下面是我加了中文注释的脚本,方便大家理解
using System.Collections.Generic;
using UnityEngine;
namespace DestroyIt
{
public class MeleeArea : MonoBehaviour
{
public int damageAmount = 30; // 伤害值
public int repairAmount = 20; // 修复值
public float meleeRadius = 1.3f; // 攻击半径
public float additionalForceAmount = 150f; // 额外的力量大小
public float additionalForceRadius = 2f; // 额外的力量作用范围半径
public ParticleSystem repairEffect; // 修复特效
// 当进行近战伤害时调用
public void OnMeleeDamage()
{
Collider[] objectsInRange = Physics.OverlapSphere(transform.position, meleeRadius);
List<Destructible> damagedObjects = new List<Destructible>(); // 记录已经受到伤害的物体,以免对每个碰撞体重复造成伤害
bool hasPlayedHitEffect = false; // 是否已经播放过攻击特效
foreach (Collider col in objectsInRange)
{
// 忽略地形碰撞体
if (col is TerrainCollider) continue;
// 忽略触发器碰撞体
if (col.isTrigger) continue;
// 忽略玩家的角色控制器(即避免攻击到自己)
if (col is CharacterController && col.tag == "Player") continue;
if (!hasPlayedHitEffect) // 每次近战攻击只播放一次攻击特效
{
// 播放攻击特效
HitEffects hitEffects = col.gameObject.GetComponentInParent<HitEffects>();
if (hitEffects != null && hitEffects.effects.Count > 0)
hitEffects.PlayEffect(HitBy.Axe, transform.position, transform.forward * -1);
hasPlayedHitEffect = true;
}
// 对受到伤害的刚体施加冲击力
Rigidbody rbody = col.attachedRigidbody;
if (rbody != null)
rbody.AddForceAtPosition(transform.forward * 3f, transform.position, ForceMode.Impulse);
// 如果碰撞到的物体是可摧毁的,则造成伤害
// 只对激活且启用的父对象中的 Destructible 脚本进行操作
// 特别说明:默认情况下,地形树上的 Destructible 脚本是关闭的(以节省资源),所以我们将对其进行特殊处理,并仍然处理碰撞
Destructible[] destObjs = col.gameObject.GetComponentsInParent<Destructible>(false);
foreach (Destructible destObj in destObjs)
{
if (damagedObjects.Contains(destObj)) continue;
if (!destObj.isActiveAndEnabled && !destObj.isTerrainTree) continue;
damagedObjects.Add(destObj);
ImpactDamage meleeImpact = new ImpactDamage()
{
DamageAmount = damageAmount,
AdditionalForce = additionalForceAmount,
AdditionalForcePosition = transform.position,
AdditionalForceRadius = additionalForceRadius
};
destObj.ApplyDamage(meleeImpact);
}
}
}
// 当进行近战修复时调用
private void OnMeleeRepair()
{
Collider[] objectsInRange = Physics.OverlapSphere(transform.position, meleeRadius);
List<Destructible> repairedObjects = new List<Destructible>(); // 记录已经修复过的物体,以免重复修复
bool hasPlayedRepairEffect = false; // 是否已经播放过修复特效
// 在范围内修复物体
foreach (Collider col in objectsInRange)
{
// 忽略地形碰撞体
if (col is TerrainCollider) continue;
// 忽略触发器碰撞体
if (col.isTrigger) continue;
// 忽略玩家的角色控制器(即避免修复自己)
if (col is CharacterController && col.tag == "Player") continue;
// 如果是可摧毁的物体,则进行修复
Destructible destObj = col.gameObject.GetComponentInParent<Destructible>();
if (destObj != null &&
!repairedObjects.Contains(destObj) &&
destObj.CurrentHitPoints < destObj.TotalHitPoints &&
destObj.canBeRepaired)
{
repairedObjects.Add(destObj);
destObj.RepairDamage(repairAmount);
// 播放修复粒子特效
if (repairEffect != null && !hasPlayedRepairEffect)
{
repairEffect.GetComponent<ParticleSystem>().Clear(true);
repairEffect.Play(true);
hasPlayedRepairEffect = true;
}
}
}
}
// 在编辑器中绘制可视化调试辅助线
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(transform.position, meleeRadius);
}
}
}
一些其他问题
这里收集了一些其他人的问题,和作者的回答
问题1
回答:
问题2
它是否只在平坦的地形上工作,并且是否使用音频源来表示声距。
回答
待续
这里我只研究了DestroyIt插件的砍树功能,他的功能肯定远不止于此,其他功能你可以通过他们提供的实例去查看,当然如果后续我用到其他功能我会再来补充(我相信一定会有机会的,敬请期待)。
完结
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,以便我第一时间收到反馈,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net
一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
更多推荐
所有评论(0)