menu 宵夜律者's Blog
【Unity】如何实现 AI 的视觉检测
2021-03-22 |0 条评论
1.RayCast只使用射线检测的好处是简单易用,但仅适用于 2D 或者对高度没有要求的俯视角游戏,很多场景并不适用2.角度判断 + RayCast判断看向目标的向量与自身正前方向量的角度,若小...
message
2021-03-07 18:06:00

留言系统我们肯定都不陌生,不止是在游戏里,很多地方都有留言系统的存在
视频上的评论信息,弹幕这些都是留言系统的一种,而游戏中的留言系统可以做的更加复杂
例如魂系列游戏中的建言,《尼尔:机械纪元》结尾的玩家留言以及保护你的小飞机,这些创新让人眼前一亮

有一个更有趣的设计,来自《Moirai》这款免费的像素游戏
简略的讲一下它的设计,在游戏里你会在洞穴里遇到一个满身的血,拿着刀的NPC
你上前对话,会有四个选项

  • 你身上为什么有那么多血?
  • 你为什么拿着一把刀?
  • 你做了什么?
  • 杀了这个NPC

你得到的回答可能完全不合逻辑,NPC看起来像在胡言乱语
你会感到疑惑,但当你玩到游戏结尾,当你满身是血,手里拿着刀,又遇到了一个NPC时
系统让你回答刚才那几个问题的时候你才明白,这是一个轮回
你的回答会变成别人游玩时,他们游戏中NPC的回答
同样,如果你注意到了第四个选项,你就会明白别人可以决定在他们游戏中,“你”的生死

你的操作会影响别人的游戏体验,这很有趣

如果这一类似机制被放在 MMORPG 中,不知道会产生怎样的效果

message
2021-02-27 18:56:00
方法/模式优点缺点
Convert  And Destroy转换后 删除 原有 GameObject1.转化为 Entity 后在 Hierarchy 面板将
2.无法调试部分无法被转化的组件将会被删除
Convert And Inject GameObject转换后 保留 原有 GameObject1.由于原 GameObject 没有被删除,会出现两个物体的情况
2.无法对子层级同时进行转化
Destroy & Inject 混合使用包含 Destroy 与 Inject 的优点1.转化为 Entity 后在 Hierarchy 面板将无法调试
2.由于原 GameObject 没有被删除,会出现两个物体的情况
Companion Game Object伴随方法可以指定 GameObject 组件不被转化为 Entity 的组件,兼容 Prefab 1.转化为 Entity 后在 Hierarchy 面板将无法调试
SubScene可以将整个场景直接转化为 Entity,且可以在 Hierarchy 面板直接进行调试

方法一 — 通过给 GameObject 挂载 Convert To Entity 组件来进行转换

挂载后,运行时将会自动转化为 Entity ,但并非所有组件都能被转化为 Entity 的 Component
可以通过更改 Conversion Mode 来更改转化的模式
Convert And Destroy 模式会将该 GameObject 的子层级一并转化,且保持父子级关系,但如遇到无法转化的组件时会直接删除
Convert And Inject Game Object 模式在转化时会保留原有组件,但会导致 Mesh Renderer 与 Hybrid Renderer 同时渲染,出现两个相同物体的情况,同时该模式无法转化子层级对象

方法二 — Destroy & Inject 混合使用

父物体与子物体同时挂载 Convert To Entity 组件
父物体为 Destroy 模式,子物体为 Inject 模式 (经测试,父物体为 Inject,子物体为 Destroy 时,子物体将不会进行转化)
此时将会同时获得两种模式的好处,在保持父子级关系的同时,子物体的组件会被保留

方法三 — 继承 IConvertGameObjectToEntity 接口,实现 Convert 方法

该方法通常用于编写 Authoring ,在 Convert 可以加入我们想要在转化时同时加入的 Component 信息
这样我们可以还在 Inspector 窗口更改参数,方便调试
注意:GameObject 依然需要挂载 Convert To Entity 组件
示例:

public struct CameraAimInfo : IComponentData {
    public float distance;
    public float theta;
}

public class CameraAuthoring : MonoBehaviour, IConvertGameObjectToEntity {
    public float distance;
    public float theta;

public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) {
        dstManager.AddComponentData(entity, new CameraAimInfo() {
            distance = distance,
            theta = theta
        });
    }
}

方法四 — Companion Game Object 伴随方法

它会创建一个新的 GameObject 来"伴随"(companion)被转换的数据,并用它来选择你想保留的组件

当我们的 GameObject 中有几个不想被转化或无法转化的组件时,可以使用 AddHybridComponent 这个方法

示例:

public class Test : MonoBehaviour, IConvertGameObjectToEntity {
    public Button button;
    public Image image;
    public Text text;
    public ParticleSystem particleCompanion;
    public ParticleSystemRenderer rendererCompanion;

public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) {
    conversionSystem.AddHybridComponent(button);
    conversionSystem.AddHybridComponent(text);
    conversionSystem.AddHybridComponent(image);
    conversionSystem.AddHybridComponent(particleCompanion);
    conversionSystem.AddHybridComponent(rendererCompanion);
    }
}

方法五 — [GenerateAuthoringComponent]

这个并不算转化方法,只是能够在转化的时候更方便的加上 Component
可以通过添加  [GenerateAuthoringComponent] 属性标签让 ComponentData 可以被直接挂载

注意:字段的访问类型必须为 public,且依然需要挂载 Convert To Entity

示例:

[GenerateAuthoringComponent]
public struct SpeedComponent : IComponentData {
    public float speed;
}

[GenerateAuthoringComponent]
public struct TagPlayer : IComponentData {}

GenerateAuthoringComponent测试.png

方法六 — 使用 SubScene 组件可以实现整个场景的 Entity 转化

通过 SubScene 转化的物体可以实现一边在 Hierarchy 中修改 GameObject,一边实时的同步到 LocalToWorld / Translation 中,并且不会出现两个物体的情况,仅由 Hybrid Renderer 负责渲染,尽管物体已经被转化为 Entity 并且 Destroy,但在 Hierarchy 中仍然可以选中物体并同步移动。

注意:在 Scene 窗口想要调试 Entity 场景需要勾选 SubScene 右侧的 Toggle

参考文章:Game Object Conversion and SubScene

【Unity】关于射击扩散的几种办法
2021-02-14 |0 条评论
建议阅读缩放比例:150%前言在多数射击游戏中,子弹的弹道通常不是固定的,而是在一个区域范围内变化的,有固定弹道变化,如 CS:GO,也有随机的弹道变化,本文主要讲解如何制作随机的弹道。制作随机...
message
2021-01-30 18:08:00

Run

Run 是直接在主线程上执行的,这个没什么需要解释的

Schedule 和 ScheduleParallel的区别

Schedule 和 ScheduleParallel 都是放在多线程上并发执行的

我目前的理解是, Schedule 是在每一个 Foreach 后生成一个 Job
而 ScheduleParallel 划分 Job 是根据 Chunk 生成的,Chunk 是按 EntityArchetype 分配的
当一个  Chunk 的空间满了后,会再生成一个 Chunk,而这每一个 Chunk 都会成为一个 Job

所以从执行效率来看,ScheduleParallel 的大多数情况应该是优于 Schedule 的
而当我们只有一个 Chunk 的时候,Schedule 和 ScheduleParallel 的效果应该是一样的

message
2021-01-21 21:13:00

使用 Convert To Entity 组件

这个可能是最简单方便的办法了,在场景中找到想要转换的 GameObject ,挂载 Convert To Entity 就可以进行转换了

需要提的一点是,这个组件有两种 Conversion Mode

Convert  And Destroy转换后 删除 原有 GameObject
Convert And Inject GameObject转换后 保留 原有 GameObject

使用 EntityManager 创建实体

这个应该是最常用的办法了,生成的Entity会生成在和 EntityManager 相同的 World 中

EntityManager.CreateEntity( )可以什么参数都不填,生成一个空的 Entity
EntityManager.CreateEntity(params ComponentType[])填入不定项个 ComponentType,可以直接生成带有这个 Component的Entity
EntityManager.CreateEntity(EntityArchetype)利用原型 Archetype 来生成 Entity
EntityManager.Instantiate(Entity)克隆一个现有的 Entity

创建一个Spawner来生成实体

我们可以创建一个用来生成的类 Spawner ,继承 MonoBehaviour ,并实现 IDeclareReferencedPrefabs ,  IConvertGameObjectToEntity 接口

这个时候需要我们去实现接口中的两个方法,其中DeclareReferencedPrefabs的操作是referencedPrefabs.Add(Prefab)
这个Prefab是我们外部加载的GameObject,这个方法会在场景中生成一个Entity类型的一个Prefab

之后我们来实现Convert这个方法
首先我们来创建一个ComponentData,我们要确保这个里面包含Entity字段,并在Convert这个方法里使用conversionSystem.GetPrimaryEntity()将这个 Prefab 转化为 Entity 加载进去

最后我们使用dstManager.AddComponentData()方法,将这个ComponentData挂载到我们之前创建好的Entity当中

此时,我们就可以利用这个Entity来创建我们外部加载的Prefab了~

【Unity】优化 —— 统一资源管理器
2021-01-15 |0 条评论
建议阅读缩放比例:150%本文技术推荐与对象池一起使用 优化—— 关于对象池为什么需要统一资源管理在之前的对象池中,我们经常需要做大量重复的动态获取,每次生成都要去 Resources.Load...
【Unity】优化 —— 关于对象池
2021-01-11 |0 条评论
建议阅读缩放比例:150%对象池是什么? 很明显,就是一个用来装对象的大池子,通常我们称拥有这种池子的人为海王(不是)在游戏运行中,经常会出现大量重复的物体,我们需要不断的去生成和删除这些对象,...
【Unity】浅谈如何利用有限状态机(FSM)设计角色动画状态
2020-08-18 |1 条评论
建议阅读缩放比例:150%什么是有限状态机(Finite-state machine)在有限个状态和有限的条件下,程序只会处于一个状态之下。通过条件的触发,使得程序从一个状态切换到对应条件触发的...
【Unity】ARPG的人物移动——那些我们游玩时不曾注意的细节
2020-08-10 |0 条评论
建议阅读缩放比例:150%前言嘿!看到这里的你,请你现在回想一下,你在玩旷野之息、鬼泣、怪猎、战神、黑魂、巫师这些ARPG时,你是如何操作你的角色移动的,我没有在开玩笑啊,请你认真的回想一下。如...
加载中... 世界之底
加载更多