ECS(一)环境
从包管理器安装
安装几个必要的包,如下。
com.unity.entities.graphics
com.unity.entities
com.unity.jobs
com.unity.burst
com.unity.mathematics
com.unity.physics
如果全部安装完上面的有些包会报错的话可以卸载再重新安装试试,我也不懂什么原理,就如有事没事重启电脑一样- -
新建sub场景
我这里用Cube做了一个Enemy预制体出来。添加EnemyAuthoring脚本到预制体中。
EnemyAuthoring脚本如下
using Unity.Entities;
enum EnemyState
{
Patrol,
Attack,
Chase,
}
struct EnemyEntity : IComponentData
{
public float speed;
public EnemyState enemyState;
public float attackRange;
}
public class EnemyAuthoring : UnityEngine.MonoBehaviour
{
public float speed;
}
class EnemyBacker : Baker<EnemyAuthoring>
{
public override void Bake(EnemyAuthoring authoring)
{
Entity entity = GetEntity(authoring, TransformUsageFlags.NonUniformScale | TransformUsageFlags.Dynamic);
AddComponent(entity, new EnemyEntity
{
speed = authoring.speed,
enemyState = EnemyState.Chase,
attackRange = 3,
});
}
}
再用Sphere新建一个Player脚本,添加PlayerAuthoring脚本,PlayerAuthoring脚本如下
using Unity.Entities;
struct PlayerEntity : IComponentData
{
public float speed;
}
class PlayerAuthoring : UnityEngine.MonoBehaviour
{
public float speed;
}
class PlayerBacker : Baker<PlayerAuthoring>
{
public override void Bake(PlayerAuthoring authoring)
{
Entity entity = GetEntity(authoring, TransformUsageFlags.NonUniformScale | TransformUsageFlags.Dynamic);
AddComponent(entity, new PlayerEntity
{
speed = authoring.speed,
});
}
}
PlayerMovementSystem脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;
using Unity.Transforms;
using Unity.Physics;
using Unity.Mathematics;
//有InputSystem只支持SystemBase
public partial class PlayerMovementSystem : SystemBase
{
public InputSystem inputActions;
protected override void OnCreate()
{
inputActions = new InputSystem();
inputActions.Enable();
}
protected override void OnUpdate()
{
Vector2 input = inputActions.Move.WASD.ReadValue<Vector2>();
float2 PlayerPos = new float2(0, 0);
Entities
.WithAll<PlayerEntity>()
.ForEach((ref LocalTransform transform, ref PhysicsVelocity vel, ref PlayerEntity playerEntity) =>
{
if (input.x != 0)
{
PlayerPos += transform.Right().xz * input.x * playerEntity.speed;
}
if (input.y != 0)
{
PlayerPos += transform.Forward().xz * input.y * playerEntity.speed;
}
vel.Linear.xz = PlayerPos;
})
//.Run();
.WithBurst().ScheduleParallel();
}
}
InputSystem的设置
EnemySystem脚本
using Unity.Entities;
using Unity.Transforms;
using Unity.Physics;
using Unity.Mathematics;
using System.Numerics;
using UnityEngine;
using Unity.Burst;
[BurstCompile]
partial struct EnemyMoveJob : IJobEntity
{
public LocalTransform playerTransform;
void Execute(ref LocalTransform transform, ref EnemyEntity enemy)
{
float3 dis = playerTransform.Position - transform.Position;
float3 normalDis = math.normalize(dis);
if (enemy.enemyState == EnemyState.Chase)
{
if (math.distance(playerTransform.Position, transform.Position) < enemy.attackRange)
{
//enemy.enemyState = EnemyState.Attack;
}
else
{
transform.Position += normalDis * enemy.speed;
}
}
else if (enemy.enemyState == EnemyState.Attack)
{
if (math.distance(playerTransform.Position, transform.Position) > enemy.attackRange)
{
//enemy.enemyState = EnemyState.Chase;
}
}
}
}
[BurstCompile]
public partial struct EnemySystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
Entity playerEntity = SystemAPI.GetSingletonEntity<PlayerEntity>();
LocalTransform _playerTransform = SystemAPI.GetComponent<LocalTransform>(playerEntity);
//这是第一种方法
var jab = new EnemyMoveJob { playerTransform = _playerTransform };
jab.ScheduleParallel();
//也可以使用这种方法去实现追赶
// foreach (var (enemy, transform, entity) in SystemAPI.Query<RefRW<EnemyEntity>, RefRW<LocalTransform>>().WithEntityAccess())
// {
// float3 dis = _playerTransform.Position - transform.ValueRW.Position;
// float3 normalDis = math.normalize(dis);
// if (enemy.ValueRW.enemyState == EnemyState.Chase)
// {
// if (math.distance(_playerTransform.Position, transform.ValueRW.Position) < enemy.ValueRW.attackRange)
// {
// enemy.ValueRW.enemyState = EnemyState.Attack;
// //enemy.ValueRW.targetEntity = playEntity;
// }
// else
// {
// transform.ValueRW.Position += normalDis * enemy.ValueRW.speed;
// }
// }
// else if (enemy.ValueRW.enemyState == EnemyState.Attack)
// {
// if (math.distance(_playerTransform.Position, transform.ValueRW.Position) > enemy.ValueRW.attackRange)
// {
// enemy.ValueRW.enemyState = EnemyState.Chase;
// }
// }
// }
}
// private EntityCommandBuffer.ParallelWriter GetEntityCommandBuffer(ref SystemState state)
// {
// var ecbSingleton = SystemAPI.GetSingleton<BeginSimulationEntityCommandBufferSystem.Singleton>();
// var ecb = ecbSingleton.CreateCommandBuffer(state.WorldUnmanaged);
// return ecb.AsParallelWriter();
// }
}