该项目的目的是同时测试和演示来自 Unity DOTS 技术堆栈的多个新包。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

193 行
6.4 KiB

using System.Collections;
using System.Collections.Generic;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Sample.Core;
using UnityEngine;
using UnityEngine.VFX;
[UpdateInGroup(typeof(PresentationSystemGroup))]
[AlwaysSynchronizeSystem]
public class VFXSystem : JobComponentSystem
{
[ConfigVar(Name = "vfx.showlifetime", DefaultValue = "0", Description = "Show lifetime")]
public static ConfigVar ShowLifetime;
static readonly int positionID = Shader.PropertyToID("position");
static readonly int targetPositionID = Shader.PropertyToID("targetPosition");
static readonly int directionID = Shader.PropertyToID("direction");
class EffectTypeData
{
public VisualEffect visualEffect;
// TODO (mogensh) For performance reasons we want to stop effects that are "done". For now all effect use same timeout duration.
public float maxDuration = 4.0f;
public bool active;
public int lastTriggerTick;
public VFXEventAttribute eventAttribute;
}
// struct EffectInstance
// {
// public VFXEventAttribute eventAttribute;
// }
struct PointEffectRequest
{
public float3 position;
public float3 direction;
public VisualEffectAsset asset;
}
struct LineEffectRequest
{
public float3 start;
public float3 end;
public VisualEffectAsset asset;
}
GameObject m_rootGameObject;
List<PointEffectRequest> m_pointEffectRequests = new List<PointEffectRequest>(32);
List<LineEffectRequest> m_lineEffectRequests = new List<LineEffectRequest>(32);
Dictionary<VisualEffectAsset, EffectTypeData> m_EffectTypeData = new Dictionary<VisualEffectAsset, EffectTypeData>(32);
// private static List<EffectInstance> s_effectInstances = new List<EffectInstance>(128);
protected override void OnCreate()
{
base.OnCreate();
m_rootGameObject = new GameObject("VFXSystem");
m_rootGameObject.transform.position = Vector3.zero;
m_rootGameObject.transform.rotation = Quaternion.identity;
GameObject.DontDestroyOnLoad(m_rootGameObject);
}
public void SpawnPointEffect(VisualEffectAsset asset, float3 position, float3 direction)
{
m_pointEffectRequests.Add(new PointEffectRequest
{
asset = asset,
position = position,
direction = direction,
});
}
public void SpawnLineEffect(VisualEffectAsset asset, float3 start, float3 end)
{
m_lineEffectRequests.Add(new LineEffectRequest
{
asset = asset,
start = start,
end = end,
});
}
// public static void StopImpact(VisualEffectAsset template)
// {
// if (!s_Impacts.ContainsKey(template))
// RegisterImpactType(template);
//
// s_Impacts[template].Stop();
// }
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
inputDeps.Complete();
var gameTimeSystem = World.GetExistingSystem<GameTimeSystem>();
var tick = gameTimeSystem.GetWorldTime().tick;
// Handle request
foreach (var request in m_pointEffectRequests)
{
EffectTypeData effectType;
if (!m_EffectTypeData.TryGetValue(request.asset, out effectType))
effectType = RegisterImpactType(request.asset);
GameDebug.Log(World, ShowLifetime,"Spawn effect:" + effectType.visualEffect.name + " pos:" + request.position);
if (ShowLifetime.IntValue > 0)
{
DebugDraw.Sphere(request.position,0.4f,Color.yellow,1.0f);
Debug.DrawLine(request.position,request.position+request.direction,Color.yellow,1.0f);
}
effectType.eventAttribute.SetVector3(positionID, request.position);
effectType.eventAttribute.SetVector3(directionID, request.direction);
effectType.visualEffect.Play(effectType.eventAttribute);
effectType.visualEffect.pause = false;
effectType.lastTriggerTick = tick;
effectType.active = true;
}
m_pointEffectRequests.Clear();
foreach (var request in m_lineEffectRequests)
{
EffectTypeData effectType;
if (!m_EffectTypeData.TryGetValue(request.asset, out effectType))
effectType = RegisterImpactType(request.asset);
effectType.eventAttribute.SetVector3(positionID, request.start);
effectType.eventAttribute.SetVector3(targetPositionID, request.end);
effectType.visualEffect.Play(effectType.eventAttribute);
effectType.visualEffect.pause = false;
effectType.lastTriggerTick = tick;
effectType.active = true;
GameDebug.Log(World, ShowLifetime, "Spawn effect:" + effectType.visualEffect.name + " start:" + request.start);
if (ShowLifetime.IntValue > 0)
{
Debug.DrawLine(request.start,request.end,Color.green,1.0f);
}
}
m_lineEffectRequests.Clear();
// foreach (var effectTypeData in m_EffectTypeData.Values)
// {
// if (effectTypeData.active &&
// tick > effectTypeData.lastTriggerTick + effectTypeData.maxDuration)
// {
//// GameDebug.Log("Reinint effect:" + effectTypeData.visualEffect.name);
// effectTypeData.visualEffect.pause = true;
// effectTypeData.active = false;
// effectTypeData.visualEffect.Stop();
// effectTypeData.visualEffect.Reinit();
// }
// }
return default;
}
EffectTypeData RegisterImpactType(VisualEffectAsset template)
{
GameDebug.Assert(!m_EffectTypeData.ContainsKey(template));
GameDebug.Assert(template != null);
GameObject go = new GameObject(template.name);
go.transform.parent = m_rootGameObject.transform;
go.transform.position = Vector3.zero;
go.transform.rotation = Quaternion.identity;
go.transform.localScale = Vector3.one;
var vfx = go.AddComponent<VisualEffect>();
vfx.visualEffectAsset = template;
vfx.Reinit();
vfx.Stop();
var data = new EffectTypeData
{
visualEffect = vfx,
eventAttribute = vfx.CreateVFXEventAttribute(),
};
m_EffectTypeData.Add(template, data);
return data;
}
}