一、生成墓碑
新建脚本如下:
using Unity.Entities;
using Unity.Mathematics;
namespace ECSdemo
{
public struct GraveyardRandom : IComponentData
{
public Random Value;
}
}
扩充GraveyardMono如下:
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using Random = Unity.Mathematics.Random;
namespace ECSdemo
{
public class GraveyardMono : MonoBehaviour
{
public float2 FieldDimensions;
//float2 结构体表示一个包含两个 float 字段的结构体,记得引用命名空间
public int NumberTombstonesToSpawn;
//想要跟踪的数量
public GameObject TombstonePrefab;
//墓碑预制件
public uint RandomSeed;
}
public class GraveyardBaker : Baker<GraveyardMono>
{
public override void Bake(GraveyardMono authoring)
{
AddComponent(new GraveyardProperties
{
FieldDimensions = authoring.FieldDimensions,
NumberTombstonesToSpawn = authoring.NumberTombstonesToSpawn,
TombstonePrefab = GetEntity(authoring.TombstonePrefab)
//GetEntity:把GameObject变成Entity
});
AddComponent(new GraveyardRandom
{
Value = Random.CreateFromIndex(authoring.RandomSeed)
}) ;
}
}
}
赋个值
这边也能看到了
再写个新脚本
using Unity.Entities;
using Unity.Transforms;
namespace ECSdemo
{
public readonly partial struct GraveyardAspect:IAspect
{
public readonly Entity Entity;
private readonly TransformAspect transformAspect;
private readonly RefRO<GraveyardProperties> _graveyardProperties;
private readonly RefRW<GraveyardRandom> _graveyardRandom;
}
}
添加新脚本
using Unity.Burst;
using Unity.Entities;
namespace ECSdemo
{
[BurstCompile]
[UpdateInGroup(typeof(InitializationSystemGroup))]
public partial struct SpawnTombstoneSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
}
[BurstCompile]
public void OnDestroy(ref SystemState state)
{
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.Enabled = false;
}
}
}
点击运行就能看到啦
继续更新如下脚本:
using Unity.Entities;
using Unity.Transforms;
namespace ECSdemo
{
public readonly partial struct GraveyardAspect:IAspect
{
public readonly Entity Entity;
private readonly TransformAspect transformAspect;
private readonly RefRO<GraveyardProperties> _graveyardProperties;
private readonly RefRW<GraveyardRandom> _graveyardRandom;
public int NumberTombstonesToSpawn => _graveyardProperties.ValueRO.NumberTombstonesToSpawn;
public Entity TombstonePrefab => _graveyardProperties.ValueRO.TombstonePrefab;
}
}
using ECSdemo;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
namespace ECSdemo
{
[BurstCompile]
[UpdateInGroup(typeof(InitializationSystemGroup))]
public partial struct SpawnTombstoneSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<GraveyardProperties>();
}
[BurstCompile]
public void OnDestroy(ref SystemState state)
{
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.Enabled = false;
var graveyardEntity = SystemAPI.GetSingletonEntity<GraveyardProperties>();
var graveyard = SystemAPI.GetAspectRW<GraveyardAspect>(graveyardEntity);
var ecb = new EntityCommandBuffer(Allocator.Temp);
for (var i = 0; i < graveyard.NumberTombstonesToSpawn; i++)
{
ecb.Instantiate(graveyard.TombstonePrefab);
}
ecb.Playback(state.EntityManager);
}
}
}
点击运行,能看见有了很多墓碑,应该有250个
继续更新代码,给墓碑随机位置
using ECSdemo;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
namespace ECSdemo
{
[BurstCompile]
[UpdateInGroup(typeof(InitializationSystemGroup))]
public partial struct SpawnTombstoneSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<GraveyardProperties>();
}
[BurstCompile]
public void OnDestroy(ref SystemState state)
{
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.Enabled = false;
var graveyardEntity = SystemAPI.GetSingletonEntity<GraveyardProperties>();
var graveyard = SystemAPI.GetAspectRW<GraveyardAspect>(graveyardEntity);
var ecb = new EntityCommandBuffer(Allocator.Temp);
for (var i = 0; i < graveyard.NumberTombstonesToSpawn; i++)
{
var newTombstone = ecb.Instantiate(graveyard.TombstonePrefab);
var newTombstoneTransform=graveyard.GetRandomTombstoneTransform();
ecb.SetComponent(newTombstone,new LocalToWorldTransform { Value = newTombstoneTransform });
}
ecb.Playback(state.EntityManager);
}
}
}
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
namespace ECSdemo
{
public readonly partial struct GraveyardAspect:IAspect
{
public readonly Entity Entity;
private readonly TransformAspect _transformAspect;
private readonly RefRO<GraveyardProperties> _graveyardProperties;
private readonly RefRW<GraveyardRandom> _graveyardRandom;
public int NumberTombstonesToSpawn => _graveyardProperties.ValueRO.NumberTombstonesToSpawn;
public Entity TombstonePrefab => _graveyardProperties.ValueRO.TombstonePrefab;
public UniformScaleTransform GetRandomTombstoneTransform()
{
return new UniformScaleTransform
{
Position = GetRandomPosition(),
Rotation = quaternion.identity,
Scale =1f
};
}
private float3 GetRandomPosition()
{
float3 randomPosition;
randomPosition = _graveyardRandom.ValueRW.Value.NextFloat3(MinCorner, MaxCorner);
return randomPosition;
}
private float3 MinCorner => _transformAspect.Position - HalfDimensions;
private float3 MaxCorner => _transformAspect.Position + HalfDimensions;
private float3 HalfDimensions => new()
{
x = _graveyardProperties.ValueRO.FieldDimensions.x * 0.5f,
y = 0f,
z = _graveyardProperties.ValueRO.FieldDimensions.y * 0.5f
};
}
}
随机位置墓碑出来了!(调整了下大脑和地板的大小)
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
namespace ECSdemo
{
public readonly partial struct GraveyardAspect:IAspect
{
public readonly Entity Entity;
private readonly TransformAspect _transformAspect;
private readonly RefRO<GraveyardProperties> _graveyardProperties;
private readonly RefRW<GraveyardRandom> _graveyardRandom;
public int NumberTombstonesToSpawn => _graveyardProperties.ValueRO.NumberTombstonesToSpawn;
public Entity TombstonePrefab => _graveyardProperties.ValueRO.TombstonePrefab;
public UniformScaleTransform GetRandomTombstoneTransform()
{
return new UniformScaleTransform
{
Position = GetRandomPosition(),
Rotation = GetRandomRotation(),
Scale = GetRandomScale(0.5f)
};
}
private float3 GetRandomPosition()
{
float3 randomPosition;
do
{
randomPosition = _graveyardRandom.ValueRW.Value.NextFloat3(MinCorner, MaxCorner);
} while (math.distancesq(_transformAspect.Position, randomPosition)<=BRAIN_SAFETY_RADIUS_SQ);
return randomPosition;
}
private float3 MinCorner => _transformAspect.Position - HalfDimensions;
private float3 MaxCorner => _transformAspect.Position + HalfDimensions;
private float3 HalfDimensions => new()
{
x = _graveyardProperties.ValueRO.FieldDimensions.x * 0.5f,
y = 0f,
z = _graveyardProperties.ValueRO.FieldDimensions.y * 0.5f
};
private const float BRAIN_SAFETY_RADIUS_SQ = 100;
private quaternion GetRandomRotation() => quaternion.RotateY(_graveyardRandom.ValueRW.Value.NextFloat(-0.25f, 0.25f));
private float GetRandomScale(float min) => _graveyardRandom.ValueRW.Value.NextFloat(min, 1f);
}
}
继续更新代码,产生随机大小
二、生成僵尸
添加新脚本
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
namespace TMG.Zombies
{
public struct ZombieSpawnPoints : IComponentData
{
public NativeArray<float3> Value;
}
}
更新脚本
using TMG.Zombies;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using Random = Unity.Mathematics.Random;
namespace ECSdemo
{
public class GraveyardMono : MonoBehaviour
{
public float2 FieldDimensions;
//float2 结构体表示一个包含两个 float 字段的结构体,记得引用命名空间
public int NumberTombstonesToSpawn;
//想要跟踪的数量
public GameObject TombstonePrefab;
//墓碑预制件
public uint RandomSeed;
}
public class GraveyardBaker : Baker<GraveyardMono>
{
public override void Bake(GraveyardMono authoring)
{
AddComponent(new GraveyardProperties
{
FieldDimensions = authoring.FieldDimensions,
NumberTombstonesToSpawn = authoring.NumberTombstonesToSpawn,
TombstonePrefab = GetEntity(authoring.TombstonePrefab)
//GetEntity:把GameObject变成Entity
});
AddComponent(new GraveyardRandom
{
Value = Random.CreateFromIndex(authoring.RandomSeed)
}) ;
AddComponent<ZombieSpawnPoints>();
}
}
}
using TMG.Zombies;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
namespace ECSdemo
{
public readonly partial struct GraveyardAspect:IAspect
{
public readonly Entity Entity;
private readonly TransformAspect _transformAspect;
private readonly RefRO<GraveyardProperties> _graveyardProperties;
private readonly RefRW<GraveyardRandom> _graveyardRandom;
private readonly RefRW<ZombieSpawnPoints> _zombieSpawnPoints;
public int NumberTombstonesToSpawn => _graveyardProperties.ValueRO.NumberTombstonesToSpawn;
public Entity TombstonePrefab => _graveyardProperties.ValueRO.TombstonePrefab;
public NativeArray<float3> ZombieSpawnPoints
{
get => _zombieSpawnPoints.ValueRO.Value;
set => _zombieSpawnPoints.ValueRW.Value=value;
}
public UniformScaleTransform GetRandomTombstoneTransform()
{
return new UniformScaleTransform
{
Position = GetRandomPosition(),
Rotation = GetRandomRotation(),
Scale = GetRandomScale(0.5f)
};
}
private float3 GetRandomPosition()
{
float3 randomPosition;
do
{
randomPosition = _graveyardRandom.ValueRW.Value.NextFloat3(MinCorner, MaxCorner);
} while (math.distancesq(_transformAspect.Position, randomPosition)<=BRAIN_SAFETY_RADIUS_SQ);
return randomPosition;
}
private float3 MinCorner => _transformAspect.Position - HalfDimensions;
private float3 MaxCorner => _transformAspect.Position + HalfDimensions;
private float3 HalfDimensions => new()
{
x = _graveyardProperties.ValueRO.FieldDimensions.x * 0.5f,
y = 0f,
z = _graveyardProperties.ValueRO.FieldDimensions.y * 0.5f
};
private const float BRAIN_SAFETY_RADIUS_SQ = 100;
private quaternion GetRandomRotation() => quaternion.RotateY(_graveyardRandom.ValueRW.Value.NextFloat(-0.25f, 0.25f));
private float GetRandomScale(float min) => _graveyardRandom.ValueRW.Value.NextFloat(min, 1f);
}
}
using ECSdemo;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
namespace ECSdemo
{
[BurstCompile]
[UpdateInGroup(typeof(InitializationSystemGroup))]
public partial struct SpawnTombstoneSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<GraveyardProperties>();
}
[BurstCompile]
public void OnDestroy(ref SystemState state)
{
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.Enabled = false;
var graveyardEntity = SystemAPI.GetSingletonEntity<GraveyardProperties>();
var graveyard = SystemAPI.GetAspectRW<GraveyardAspect>(graveyardEntity);
var ecb = new EntityCommandBuffer(Allocator.Temp);
var spawnPionts = new NativeList<float3>(Allocator.Temp);
var tombstoneOffset = new float3(0f, -2f, 1f);
for (var i = 0; i < graveyard.NumberTombstonesToSpawn; i++)
{
var newTombstone = ecb.Instantiate(graveyard.TombstonePrefab);
var newTombstoneTransform=graveyard.GetRandomTombstoneTransform();
ecb.SetComponent(newTombstone,new LocalToWorldTransform { Value = newTombstoneTransform });
var newZombieSpawnPoint = newTombstoneTransform.Position + tombstoneOffset;
spawnPionts.Add(newZombieSpawnPoint);
}
graveyard.ZombieSpawnPoints = spawnPionts.ToArray(Allocator.Persistent);
ecb.Playback(state.EntityManager);
}
}
}
做一个僵尸预制体,要确保父物体y轴为0,也就是脚踩地面上
更新脚本
using Unity.Entities;
using Unity.Mathematics;
namespace ECSdemo
{
public struct GraveyardProperties : IComponentData
//继承这个接口,让这个结构体变成组件,记得引用命名空间
{
public float2 FieldDimensions;
//float2 结构体表示一个包含两个 float 字段的结构体,记得引用命名空间
public int NumberTombstonesToSpawn;
//想要跟踪的数量
public Entity TombstonePrefab;
//墓碑预制件
public Entity ZombiePrefab;
public float ZombieSpawnRate;
}
public struct ZombieSpawnTimer:IComponentData
{
public float Value;
}
}
using TMG.Zombies;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using Random = Unity.Mathematics.Random;
namespace ECSdemo
{
public class GraveyardMono : MonoBehaviour
{
public float2 FieldDimensions;
//float2 结构体表示一个包含两个 float 字段的结构体,记得引用命名空间
public int NumberTombstonesToSpawn;
//想要跟踪的数量
public GameObject TombstonePrefab;
//墓碑预制件
public uint RandomSeed;
public GameObject Zombieprefab;
public float ZombieSpawnRate;
}
public class GraveyardBaker : Baker<GraveyardMono>
{
public override void Bake(GraveyardMono authoring)
{
AddComponent(new GraveyardProperties
{
FieldDimensions = authoring.FieldDimensions,
NumberTombstonesToSpawn = authoring.NumberTombstonesToSpawn,
TombstonePrefab = GetEntity(authoring.TombstonePrefab),
//GetEntity:把GameObject变成Entity
ZombiePrefab=GetEntity(authoring.Zombieprefab),
ZombieSpawnRate= authoring.ZombieSpawnRate
});
AddComponent(new GraveyardRandom
{
Value = Random.CreateFromIndex(authoring.RandomSeed)
}) ;
AddComponent<ZombieSpawnPoints>();
AddComponent<ZombieSpawnTimer>();
}
}
}
进行一个赋值
using TMG.Zombies;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
namespace ECSdemo
{
public readonly partial struct GraveyardAspect:IAspect
{
public readonly Entity Entity;
private readonly TransformAspect _transformAspect;
private readonly RefRO<GraveyardProperties> _graveyardProperties;
private readonly RefRW<GraveyardRandom> _graveyardRandom;
private readonly RefRW<ZombieSpawnPoints> _zombieSpawnPoints;
private readonly RefRW<ZombieSpawnTimer> _zombieSpawnTimer;
public int NumberTombstonesToSpawn => _graveyardProperties.ValueRO.NumberTombstonesToSpawn;
public Entity TombstonePrefab => _graveyardProperties.ValueRO.TombstonePrefab;
public NativeArray<float3> ZombieSpawnPoints
{
get => _zombieSpawnPoints.ValueRO.Value;
set => _zombieSpawnPoints.ValueRW.Value=value;
}
public UniformScaleTransform GetRandomTombstoneTransform()
{
return new UniformScaleTransform
{
Position = GetRandomPosition(),
Rotation = GetRandomRotation(),
Scale = GetRandomScale(0.5f)
};
}
private float3 GetRandomPosition()
{
float3 randomPosition;
do
{
randomPosition = _graveyardRandom.ValueRW.Value.NextFloat3(MinCorner, MaxCorner);
} while (math.distancesq(_transformAspect.Position, randomPosition)<=BRAIN_SAFETY_RADIUS_SQ);
return randomPosition;
}
private float3 MinCorner => _transformAspect.Position - HalfDimensions;
private float3 MaxCorner => _transformAspect.Position + HalfDimensions;
private float3 HalfDimensions => new()
{
x = _graveyardProperties.ValueRO.FieldDimensions.x * 0.5f,
y = 0f,
z = _graveyardProperties.ValueRO.FieldDimensions.y * 0.5f
};
private const float BRAIN_SAFETY_RADIUS_SQ = 100;
private quaternion GetRandomRotation() => quaternion.RotateY(_graveyardRandom.ValueRW.Value.NextFloat(-0.25f, 0.25f));
private float GetRandomScale(float min) => _graveyardRandom.ValueRW.Value.NextFloat(min, 1f);
public float2 GetRandomOffset()
{
return _graveyardRandom.ValueRW.Value.NextFloat2();
}
public float ZombieSpawnTimer
{
get => _zombieSpawnTimer.ValueRO.Value;
set => _zombieSpawnTimer.ValueRW.Value = value;
}
public bool TimeToSpawnZombie => ZombieSpawnTimer <= 0f;
}
}