【推荐100个unity插件之17】具有可破坏/砍倒unity地形树木能力的破坏系统,实现unity砍树效果 —— DestroyIt - Destruction System

简介: 【推荐100个unity插件之17】具有可破坏/砍倒unity地形树木能力的破坏系统,实现unity砍树效果 —— DestroyIt - Destruction System

前言

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:这里破坏树的预制体和原树的预制体之间碰撞器配置不太好,如果碰撞器的位置一致且不会在地下,那么效果肯定会更好,实现真正意义上的无缝衔接

image.png

攻击具体是如何实现的呢(补充)

如果你想自己创建人物控制器,可能就需要用到,当然通常我们不会用它自带的人物控制脚本

其实就是在人物身上挂载个攻击区域检测脚本

点击攻击时调用里面的方法(当然还包括修复的方法),下面是我加了中文注释的脚本,方便大家理解

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插件的砍树功能,他的功能肯定远不止于此,其他功能你可以通过他们提供的实例去查看,当然如果后续我用到其他功能我会再来补充(我相信一定会有机会的,敬请期待)。

目录
相关文章
|
3月前
|
图形学 开发者 存储
超越基础教程:深度拆解Unity地形编辑器的每一个隐藏角落,让你的游戏世界既浩瀚无垠又细节满满——从新手到高手的全面技巧升级秘籍
【8月更文挑战第31天】Unity地形编辑器是游戏开发中的重要工具,可快速创建复杂多变的游戏环境。本文通过比较不同地形编辑技术,详细介绍如何利用其功能构建广阔且精细的游戏世界,并提供具体示例代码,展示从基础地形绘制到植被与纹理添加的全过程。通过学习这些技巧,开发者能显著提升游戏画面质量和玩家体验。
148 3
|
3月前
|
传感器 开发工具 vr&ar
ManoMotion⭐二、Unity手势识别插件简介,及效果录屏
ManoMotion⭐二、Unity手势识别插件简介,及效果录屏
|
2月前
|
图形学 C++ C#
Unity插件开发全攻略:从零起步教你用C++扩展游戏功能,解锁Unity新玩法的详细步骤与实战技巧大公开
【8月更文挑战第31天】Unity 是一款功能强大的游戏开发引擎,支持多平台发布并拥有丰富的插件生态系统。本文介绍 Unity 插件开发基础,帮助读者从零开始编写自定义插件以扩展其功能。插件通常用 C++ 编写,通过 Mono C# 运行时调用,需在不同平台上编译。文中详细讲解了开发环境搭建、简单插件编写及在 Unity 中调用的方法,包括创建 C# 封装脚本和处理跨平台问题,助力开发者提升游戏开发效率。
201 0
|
2月前
|
图形学 开发者 UED
Unity游戏开发必备技巧:深度解析事件系统运用之道,从生命周期回调到自定义事件,打造高效逻辑与流畅交互的全方位指南
【8月更文挑战第31天】在游戏开发中,事件系统是连接游戏逻辑与用户交互的关键。Unity提供了多种机制处理事件,如MonoBehaviour生命周期回调、事件系统组件及自定义事件。本文介绍如何有效利用这些机制,包括创建自定义事件和使用Unity内置事件系统提升游戏体验。通过合理安排代码执行时机,如在Awake、Start等方法中初始化组件,以及使用委托和事件处理复杂逻辑,可以使游戏更加高效且逻辑清晰。掌握这些技巧有助于开发者更好地应对游戏开发挑战。
120 0
|
3月前
|
图形学 C# 开发者
Unity粒子系统全解析:从基础设置到高级编程技巧,教你轻松玩转绚丽多彩的视觉特效,打造震撼游戏画面的终极指南
【8月更文挑战第31天】粒子系统是Unity引擎的强大功能,可创建动态视觉效果,如火焰、爆炸等。本文介绍如何在Unity中使用粒子系统,并提供示例代码。首先创建粒子系统,然后调整Emission、Shape、Color over Lifetime等模块参数,实现所需效果。此外,还可通过C#脚本实现更复杂的粒子效果,增强游戏视觉冲击力和沉浸感。
180 0
|
3月前
|
开发者 图形学 前端开发
绝招放送:彻底解锁Unity UI系统奥秘,五大步骤教你如何缔造令人惊叹的沉浸式游戏体验,从Canvas到动画,一步一个脚印走向大师级UI设计
【8月更文挑战第31天】随着游戏开发技术的进步,UI成为提升游戏体验的关键。本文探讨如何利用Unity的UI系统创建美观且功能丰富的界面,包括Canvas、UI元素及Event System的使用,并通过具体示例代码展示按钮点击事件及淡入淡出动画的实现过程,助力开发者打造沉浸式的游戏体验。
95 0
|
3月前
|
图形学
Unity动画☀️Unity动画系统Bug集合
Unity动画☀️Unity动画系统Bug集合
|
5月前
|
存储 JSON 关系型数据库
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
159 2
|
5月前
|
图形学
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(下)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
81 0
|
5月前
|
图形学 容器
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(上)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
80 0