增加了 Unity 适配器
This commit is contained in:
parent
af702cbbda
commit
a3ec9df001
@ -13,10 +13,13 @@
|
||||
<ItemGroup>
|
||||
<Compile Remove="obj\**" />
|
||||
<Compile Remove="src\Tests\**" />
|
||||
<Compile Remove="src\Adapters\**" />
|
||||
<EmbeddedResource Remove="obj\**" />
|
||||
<EmbeddedResource Remove="src\Tests\**" />
|
||||
<EmbeddedResource Remove="src\Adapters\**" />
|
||||
<None Remove="obj\**" />
|
||||
<None Remove="src\Tests\**" />
|
||||
<None Remove="src\Adapters\**" />
|
||||
</ItemGroup>
|
||||
|
||||
</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
|
||||
{
|
||||
/// <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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user