增加了 Unity 适配器
This commit is contained in:
parent
af702cbbda
commit
a3ec9df001
@ -13,10 +13,13 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="obj\**" />
|
<Compile Remove="obj\**" />
|
||||||
<Compile Remove="src\Tests\**" />
|
<Compile Remove="src\Tests\**" />
|
||||||
|
<Compile Remove="src\Adapters\**" />
|
||||||
<EmbeddedResource Remove="obj\**" />
|
<EmbeddedResource Remove="obj\**" />
|
||||||
<EmbeddedResource Remove="src\Tests\**" />
|
<EmbeddedResource Remove="src\Tests\**" />
|
||||||
|
<EmbeddedResource Remove="src\Adapters\**" />
|
||||||
<None Remove="obj\**" />
|
<None Remove="obj\**" />
|
||||||
<None Remove="src\Tests\**" />
|
<None Remove="src\Tests\**" />
|
||||||
|
<None Remove="src\Adapters\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
32
src/Adapters/UnityExtensions.cs
Normal file
32
src/Adapters/UnityExtensions.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Adapters
|
||||||
|
{
|
||||||
|
public static class UnityExtensions
|
||||||
|
{
|
||||||
|
public static Vector3D ToVector3D(this Vector3 v)
|
||||||
|
{
|
||||||
|
return new Vector3D(v.x, v.y, v.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 ToVector3(this Vector3D v)
|
||||||
|
{
|
||||||
|
return new Vector3((float)v.X, (float)v.Y, (float)v.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Orientation ToOrientation(this Quaternion q)
|
||||||
|
{
|
||||||
|
Vector3 euler = q.eulerAngles;
|
||||||
|
return new Orientation(euler.x, euler.y, euler.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion ToQuaternion(this Orientation o)
|
||||||
|
{
|
||||||
|
return Quaternion.Euler(
|
||||||
|
(float)o.Pitch,
|
||||||
|
(float)o.Yaw,
|
||||||
|
(float)o.Roll
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/Adapters/UnityMissile.cs
Normal file
31
src/Adapters/UnityMissile.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Adapters
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unity导弹组件
|
||||||
|
/// </summary>
|
||||||
|
public class UnityMissile : UnitySimulationElement
|
||||||
|
{
|
||||||
|
[SerializeField]
|
||||||
|
private string missileId;
|
||||||
|
[SerializeField]
|
||||||
|
private MissileProperties missileProperties;
|
||||||
|
|
||||||
|
private Missile _missile;
|
||||||
|
|
||||||
|
protected override SimulationElement CreateSimulationElement()
|
||||||
|
{
|
||||||
|
var unityManager = FindObjectOfType<UnitySimulationManager>();
|
||||||
|
_missile = new Missile(missileId, transform.position.ToVector3D(),
|
||||||
|
transform.rotation.ToOrientation(), unityManager, missileProperties);
|
||||||
|
return _missile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unity特有的功能,如粒子效果
|
||||||
|
public void OnMissileLaunch()
|
||||||
|
{
|
||||||
|
GetComponent<ParticleSystem>()?.Play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/Adapters/UnitySimulationElement.cs
Normal file
42
src/Adapters/UnitySimulationElement.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Adapters
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unity仿真元素基类,将我们的SimulationElement适配到MonoBehaviour
|
||||||
|
/// </summary>
|
||||||
|
public abstract class UnitySimulationElement : MonoBehaviour
|
||||||
|
{
|
||||||
|
protected SimulationElement SimElement { get; private set; }
|
||||||
|
|
||||||
|
protected virtual void Awake()
|
||||||
|
{
|
||||||
|
// 创建对应的仿真元素
|
||||||
|
SimElement = CreateSimulationElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Update()
|
||||||
|
{
|
||||||
|
// 使用Unity的时间步长
|
||||||
|
SimElement?.Update(Time.deltaTime);
|
||||||
|
|
||||||
|
// 同步位置和旋转
|
||||||
|
if (SimElement != null)
|
||||||
|
{
|
||||||
|
transform.position = new Vector3(
|
||||||
|
(float)SimElement.Position.X,
|
||||||
|
(float)SimElement.Position.Y,
|
||||||
|
(float)SimElement.Position.Z
|
||||||
|
);
|
||||||
|
|
||||||
|
transform.rotation = Quaternion.Euler(
|
||||||
|
(float)SimElement.Orientation.Pitch,
|
||||||
|
(float)SimElement.Orientation.Yaw,
|
||||||
|
(float)SimElement.Orientation.Roll
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract SimulationElement CreateSimulationElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
166
src/Adapters/UnitySimulationManager.cs
Normal file
166
src/Adapters/UnitySimulationManager.cs
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Events;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using ActiveProtect.Simulation;
|
||||||
|
using ActiveProtect.Models;
|
||||||
|
using ActiveProtect.Utility;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Adapters
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unity仿真管理器适配器,将Unity的事件系统适配到我们的接口
|
||||||
|
/// </summary>
|
||||||
|
public class UnitySimulationManager : MonoBehaviour, ISimulationManager
|
||||||
|
{
|
||||||
|
// Unity事件字典,用于事件订阅和发布
|
||||||
|
private readonly Dictionary<Type, UnityEvent<SimulationEvent>> _eventDictionary
|
||||||
|
= new Dictionary<Type, UnityEvent<SimulationEvent>>();
|
||||||
|
|
||||||
|
// 仿真元素列表
|
||||||
|
private readonly List<SimulationElement> _elements = new List<SimulationElement>();
|
||||||
|
|
||||||
|
public double CurrentTime => Time.time;
|
||||||
|
|
||||||
|
// 实现非泛型的 PublishEvent
|
||||||
|
public void PublishEvent(SimulationEvent evt)
|
||||||
|
{
|
||||||
|
var eventType = evt.GetType();
|
||||||
|
if (_eventDictionary.TryGetValue(eventType, out var unityEvent))
|
||||||
|
{
|
||||||
|
unityEvent.Invoke(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实现泛型的 PublishEvent
|
||||||
|
public void PublishEvent<T>(T evt) where T : SimulationEvent
|
||||||
|
{
|
||||||
|
PublishEvent(evt as SimulationEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent
|
||||||
|
{
|
||||||
|
var eventType = typeof(T);
|
||||||
|
if (!_eventDictionary.ContainsKey(eventType))
|
||||||
|
{
|
||||||
|
_eventDictionary[eventType] = new UnityEvent<SimulationEvent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_eventDictionary[eventType].AddListener(evt =>
|
||||||
|
{
|
||||||
|
if (evt is T typedEvent)
|
||||||
|
{
|
||||||
|
handler(typedEvent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent
|
||||||
|
{
|
||||||
|
var eventType = typeof(T);
|
||||||
|
if (_eventDictionary.ContainsKey(eventType))
|
||||||
|
{
|
||||||
|
// Unity的事件系统不支持直接移除特定处理器,需要重新创建事件
|
||||||
|
var newEvent = new UnityEvent<SimulationEvent>();
|
||||||
|
_eventDictionary[eventType] = newEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsubscribeAllEvents(SimulationElement element)
|
||||||
|
{
|
||||||
|
// 在Unity中,我们可能需要遍历所有事件类型并移除相关的监听器
|
||||||
|
foreach (var eventPair in _eventDictionary)
|
||||||
|
{
|
||||||
|
eventPair.Value.RemoveAllListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimulationElement GetEntityById(string id)
|
||||||
|
{
|
||||||
|
// 首先在我们的列表中查找
|
||||||
|
var element = _elements.Find(e => e.Id == id);
|
||||||
|
if (element != null) return element;
|
||||||
|
|
||||||
|
// 如果没找到,使用Unity的查找机制
|
||||||
|
var go = GameObject.Find(id);
|
||||||
|
var unityElement = go?.GetComponent<UnitySimulationElement>();
|
||||||
|
return unityElement?.SimElement ?? throw new InvalidOperationException($"Entity with id {id} not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddElement(SimulationElement element)
|
||||||
|
{
|
||||||
|
if (!_elements.Contains(element))
|
||||||
|
{
|
||||||
|
_elements.Add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SimulationElement> GetElements()
|
||||||
|
{
|
||||||
|
return new List<SimulationElement>(_elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleTargetHit()
|
||||||
|
{
|
||||||
|
// 遍历所有活跃的导弹和坦克
|
||||||
|
var missiles = _elements.FindAll(e => e is MissileBase && e.IsActive);
|
||||||
|
var tanks = _elements.FindAll(e => e is Tank && e.IsActive);
|
||||||
|
|
||||||
|
foreach (var missile in missiles)
|
||||||
|
{
|
||||||
|
if (missile is MissileBase actualMissile)
|
||||||
|
{
|
||||||
|
foreach (var tank in tanks)
|
||||||
|
{
|
||||||
|
if (tank is Tank actualTank)
|
||||||
|
{
|
||||||
|
double distance = Vector3D.Distance(missile.Position, tank.Position);
|
||||||
|
if (distance <= actualMissile.MissileProperties.ExplosionRadius)
|
||||||
|
{
|
||||||
|
// 发布命中事件
|
||||||
|
PublishEvent(new TargetHitEvent
|
||||||
|
{
|
||||||
|
TargetId = tank.Id,
|
||||||
|
MissileId = missile.Id
|
||||||
|
});
|
||||||
|
|
||||||
|
// 处理伤害
|
||||||
|
actualTank.TakeDamage(50, true);
|
||||||
|
Debug.Log($"目标 {tank.Id} 被导弹 {missile.Id} 击中");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
// 在Unity的Update中更新所有仿真元素
|
||||||
|
foreach (var element in _elements.ToArray())
|
||||||
|
{
|
||||||
|
if (element.IsActive)
|
||||||
|
{
|
||||||
|
element.Update(Time.deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理目标命中检测
|
||||||
|
HandleTargetHit();
|
||||||
|
|
||||||
|
// 清理不活跃的元素
|
||||||
|
_elements.RemoveAll(e => !e.IsActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
// 清理所有事件订阅
|
||||||
|
foreach (var eventPair in _eventDictionary)
|
||||||
|
{
|
||||||
|
eventPair.Value.RemoveAllListeners();
|
||||||
|
}
|
||||||
|
_eventDictionary.Clear();
|
||||||
|
_elements.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
src/Simulation/ISimulationManager.cs
Normal file
56
src/Simulation/ISimulationManager.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Simulation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 仿真管理器接口,定义了仿真管理器的基本功能
|
||||||
|
/// </summary>
|
||||||
|
public interface ISimulationManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 当前仿真时间
|
||||||
|
/// </summary>
|
||||||
|
double CurrentTime { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加仿真元素
|
||||||
|
/// </summary>
|
||||||
|
void AddElement(SimulationElement element);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 仿真元素列表
|
||||||
|
/// </summary>
|
||||||
|
List<SimulationElement> GetElements();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据ID获取仿真实体
|
||||||
|
/// </summary>
|
||||||
|
SimulationElement GetEntityById(string id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理目标被击中事件
|
||||||
|
/// </summary>
|
||||||
|
void HandleTargetHit();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发布仿真事件
|
||||||
|
/// </summary>
|
||||||
|
void PublishEvent(SimulationEvent evt);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 订阅仿真事件
|
||||||
|
/// </summary>
|
||||||
|
void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取消订阅仿真事件
|
||||||
|
/// </summary>
|
||||||
|
void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取消所有事件订阅
|
||||||
|
/// </summary>
|
||||||
|
void UnsubscribeAllEvents(SimulationElement element);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,57 +6,6 @@ using ActiveProtect.Utility;
|
|||||||
|
|
||||||
namespace ActiveProtect.Simulation
|
namespace ActiveProtect.Simulation
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 仿真管理器接口,定义了仿真管理器的基本功能
|
|
||||||
/// </summary>
|
|
||||||
public interface ISimulationManager
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 当前仿真时间
|
|
||||||
/// </summary>
|
|
||||||
double CurrentTime { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 添加仿真元素
|
|
||||||
/// </summary>
|
|
||||||
void AddElement(SimulationElement element);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 仿真元素列表
|
|
||||||
/// </summary>
|
|
||||||
List<SimulationElement> GetElements();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 根据ID获取仿真实体
|
|
||||||
/// </summary>
|
|
||||||
SimulationElement GetEntityById(string id);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 处理目标被击中事件
|
|
||||||
/// </summary>
|
|
||||||
void HandleTargetHit();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发布仿真事件
|
|
||||||
/// </summary>
|
|
||||||
void PublishEvent(SimulationEvent evt);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 订阅仿真事件
|
|
||||||
/// </summary>
|
|
||||||
void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 取消订阅仿真事件
|
|
||||||
/// </summary>
|
|
||||||
void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 取消所有事件订阅
|
|
||||||
/// </summary>
|
|
||||||
void UnsubscribeAllEvents(SimulationElement element);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 仿真管理器类,负责管理整个仿真过程
|
/// 仿真管理器类,负责管理整个仿真过程
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user