595 lines
19 KiB
C#
595 lines
19 KiB
C#
#if NEVER // 使用编译指令确保此文件永远不会被编译
|
||
|
||
// Unity Package集成示例代码 - 方法二:创建Unity Package
|
||
//
|
||
// 【适用场景】
|
||
// - 团队协作开发和多项目复用
|
||
// - 需要版本管理和Package Manager支持
|
||
// - 计划发布到Package Registry
|
||
//
|
||
// 【前置条件】
|
||
// 1. 按照Integration README创建完整的Package结构
|
||
// 2. 配置正确的package.json和Assembly Definition
|
||
// 3. 使用Package Manager安装或本地引用Package
|
||
//
|
||
// 【Package结构】
|
||
// com.yourcompany.threatsource/
|
||
// ├── Runtime/
|
||
// │ ├── Scripts/(本示例文件应放在此处)
|
||
// │ └── Plugins/ThreatSource.dll
|
||
// └── Samples~/BasicExample/
|
||
//
|
||
// 展示如何在Unity Package环境中使用ThreatSource仿真系统
|
||
|
||
using UnityEngine;
|
||
using System.Collections.Generic;
|
||
using ThreatSource.Simulation;
|
||
using ThreatSource.Data;
|
||
using ThreatSource.Missile;
|
||
|
||
// Package专用命名空间,避免与用户代码冲突
|
||
namespace ThreatSourceUnity
|
||
{
|
||
/// <summary>
|
||
/// ThreatSource Unity Package管理器
|
||
/// 提供Package级别的配置和管理功能
|
||
/// </summary>
|
||
public class ThreatSourcePackageManager : MonoBehaviour
|
||
{
|
||
#region 单例模式
|
||
private static ThreatSourcePackageManager _instance;
|
||
public static ThreatSourcePackageManager Instance
|
||
{
|
||
get
|
||
{
|
||
if (_instance == null)
|
||
{
|
||
_instance = FindObjectOfType<ThreatSourcePackageManager>();
|
||
if (_instance == null)
|
||
{
|
||
GameObject go = new GameObject("ThreatSourcePackageManager");
|
||
_instance = go.AddComponent<ThreatSourcePackageManager>();
|
||
DontDestroyOnLoad(go);
|
||
}
|
||
}
|
||
return _instance;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 配置属性
|
||
[Header("Package配置")]
|
||
[SerializeField] private string packageVersion = "1.1.22";
|
||
[SerializeField] private bool enableDebugLogging = true;
|
||
[SerializeField] private float simulationTimeStep = 0.02f;
|
||
|
||
[Header("资源路径配置")]
|
||
[SerializeField] private string dataPath = "StreamingAssets/ThreatSource/data";
|
||
[SerializeField] private string prefabPath = "Packages/com.yourcompany.threatsource/Runtime/Prefabs";
|
||
#endregion
|
||
|
||
#region 核心组件
|
||
private ISimulationManager _simulationManager;
|
||
private ThreatSourceDataManager _dataManager;
|
||
private Dictionary<string, GameObject> _entityGameObjects = new Dictionary<string, GameObject>();
|
||
#endregion
|
||
|
||
#region Unity生命周期
|
||
private void Awake()
|
||
{
|
||
// 确保单例
|
||
if (_instance != null && _instance != this)
|
||
{
|
||
Destroy(gameObject);
|
||
return;
|
||
}
|
||
_instance = this;
|
||
DontDestroyOnLoad(gameObject);
|
||
|
||
InitializePackage();
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
UpdateSimulation();
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
CleanupPackage();
|
||
}
|
||
#endregion
|
||
|
||
#region Package初始化
|
||
/// <summary>
|
||
/// 初始化Package
|
||
/// </summary>
|
||
private void InitializePackage()
|
||
{
|
||
try
|
||
{
|
||
LogDebug($"正在初始化ThreatSource Package v{packageVersion}");
|
||
|
||
// 验证Package环境
|
||
if (!ValidatePackageEnvironment())
|
||
{
|
||
LogError("Package环境验证失败");
|
||
return;
|
||
}
|
||
|
||
// 初始化仿真系统
|
||
_simulationManager = new SimulationManager();
|
||
_dataManager = new ThreatSourceDataManager();
|
||
|
||
// 启动仿真
|
||
_simulationManager.StartSimulation(simulationTimeStep);
|
||
|
||
// 订阅事件
|
||
SubscribeToEvents();
|
||
|
||
LogDebug("ThreatSource Package初始化完成");
|
||
}
|
||
catch (System.Exception ex)
|
||
{
|
||
LogError($"Package初始化失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证Package环境
|
||
/// </summary>
|
||
private bool ValidatePackageEnvironment()
|
||
{
|
||
// 检查数据路径
|
||
string fullDataPath = System.IO.Path.Combine(Application.streamingAssetsPath, "ThreatSource/data");
|
||
if (!System.IO.Directory.Exists(fullDataPath))
|
||
{
|
||
LogError($"数据目录不存在: {fullDataPath}");
|
||
return false;
|
||
}
|
||
|
||
// 检查Assembly Definition
|
||
if (!HasValidAssemblyDefinition())
|
||
{
|
||
LogError("Assembly Definition配置无效");
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查Assembly Definition配置
|
||
/// </summary>
|
||
private bool HasValidAssemblyDefinition()
|
||
{
|
||
// 在实际Package中,这里可以检查Assembly Definition的配置
|
||
// 例如检查引用关系、平台设置等
|
||
return true; // 简化示例
|
||
}
|
||
#endregion
|
||
|
||
#region 事件系统
|
||
/// <summary>
|
||
/// 订阅仿真事件
|
||
/// </summary>
|
||
private void SubscribeToEvents()
|
||
{
|
||
_simulationManager.Subscribe<MissileFireEvent>(OnMissileFireEvent);
|
||
_simulationManager.Subscribe<MissileExplodeEvent>(OnMissileExplodeEvent);
|
||
_simulationManager.Subscribe<FlightPhaseChangeEvent>(OnFlightPhaseChangeEvent);
|
||
}
|
||
|
||
private void OnMissileFireEvent(MissileFireEvent evt)
|
||
{
|
||
LogDebug($"Package事件: 导弹 {evt.SenderId} 向 {evt.TargetId} 发射");
|
||
|
||
// 触发Unity事件
|
||
ThreatSourceEvents.Instance.OnMissileFired?.Invoke(evt.SenderId, evt.TargetId);
|
||
}
|
||
|
||
private void OnMissileExplodeEvent(MissileExplodeEvent evt)
|
||
{
|
||
LogDebug($"Package事件: 导弹 {evt.SenderId} 在 {evt.Position} 爆炸");
|
||
|
||
// 清理GameObject
|
||
if (_entityGameObjects.TryGetValue(evt.SenderId, out GameObject missileGO))
|
||
{
|
||
Destroy(missileGO);
|
||
_entityGameObjects.Remove(evt.SenderId);
|
||
}
|
||
|
||
// 触发Unity事件
|
||
ThreatSourceEvents.Instance.OnMissileExploded?.Invoke(evt.SenderId,
|
||
CoordinateConverter.ThreatSourceToUnity(evt.Position));
|
||
}
|
||
|
||
private void OnFlightPhaseChangeEvent(FlightPhaseChangeEvent evt)
|
||
{
|
||
LogDebug($"Package事件: 导弹 {evt.SenderId} 进入 {evt.NewPhase} 阶段");
|
||
|
||
// 触发Unity事件
|
||
ThreatSourceEvents.Instance.OnFlightPhaseChanged?.Invoke(evt.SenderId, evt.NewPhase);
|
||
}
|
||
#endregion
|
||
|
||
#region 仿真管理
|
||
/// <summary>
|
||
/// 更新仿真
|
||
/// </summary>
|
||
private void UpdateSimulation()
|
||
{
|
||
if (_simulationManager != null)
|
||
{
|
||
_simulationManager.UpdateSimulation();
|
||
SyncEntityStates();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 同步实体状态
|
||
/// </summary>
|
||
private void SyncEntityStates()
|
||
{
|
||
foreach (var kvp in _entityGameObjects)
|
||
{
|
||
var entity = _simulationManager.GetEntity(kvp.Key);
|
||
if (entity?.KState != null)
|
||
{
|
||
var gameObject = kvp.Value;
|
||
gameObject.transform.position = CoordinateConverter.ThreatSourceToUnity(entity.KState.Position);
|
||
gameObject.transform.rotation = CoordinateConverter.OrientationToQuaternion(entity.KState.Orientation);
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 公共API
|
||
/// <summary>
|
||
/// 创建导弹(Package API)
|
||
/// </summary>
|
||
public string CreateMissile(string missileType, Vector3 position, string targetId)
|
||
{
|
||
try
|
||
{
|
||
var missileData = _dataManager.GetMissile(missileType);
|
||
string missileId = $"pkg_missile_{System.Guid.NewGuid():N}";
|
||
|
||
var missile = new InfraredImagingTerminalGuidanceMissile(missileId, missileData)
|
||
{
|
||
KState = new KinematicState
|
||
{
|
||
Position = CoordinateConverter.UnityToThreatSource(position),
|
||
Velocity = new ThreatSource.Simulation.Vector3(0, 0, 0),
|
||
Orientation = new Orientation(0, 0, 0)
|
||
}
|
||
};
|
||
|
||
_simulationManager.RegisterEntity(missile);
|
||
|
||
// 使用Package资源加载
|
||
var prefab = LoadPrefabFromPackage("Missile");
|
||
if (prefab != null)
|
||
{
|
||
var missileGO = Instantiate(prefab, position, Quaternion.identity);
|
||
missileGO.name = $"[Package] {missileId}";
|
||
|
||
var controller = missileGO.GetComponent<PackageMissileController>();
|
||
if (controller == null)
|
||
{
|
||
controller = missileGO.AddComponent<PackageMissileController>();
|
||
}
|
||
controller.Initialize(missileId, targetId);
|
||
|
||
_entityGameObjects[missileId] = missileGO;
|
||
}
|
||
|
||
LogDebug($"Package创建导弹: {missileId}");
|
||
return missileId;
|
||
}
|
||
catch (System.Exception ex)
|
||
{
|
||
LogError($"Package创建导弹失败: {ex.Message}");
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建目标(Package API)
|
||
/// </summary>
|
||
public string CreateTarget(string targetId, Vector3 position, Vector3 velocity)
|
||
{
|
||
try
|
||
{
|
||
var target = new BaseEquipment(targetId)
|
||
{
|
||
KState = new KinematicState
|
||
{
|
||
Position = CoordinateConverter.UnityToThreatSource(position),
|
||
Velocity = CoordinateConverter.UnityToThreatSource(velocity),
|
||
Orientation = new Orientation(0, 0, 0)
|
||
}
|
||
};
|
||
|
||
_simulationManager.RegisterEntity(target);
|
||
|
||
var prefab = LoadPrefabFromPackage("Target");
|
||
if (prefab != null)
|
||
{
|
||
var targetGO = Instantiate(prefab, position, Quaternion.identity);
|
||
targetGO.name = $"[Package] {targetId}";
|
||
_entityGameObjects[targetId] = targetGO;
|
||
}
|
||
|
||
LogDebug($"Package创建目标: {targetId}");
|
||
return targetId;
|
||
}
|
||
catch (System.Exception ex)
|
||
{
|
||
LogError($"Package创建目标失败: {ex.Message}");
|
||
return null;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 资源管理
|
||
/// <summary>
|
||
/// 从Package加载预制体
|
||
/// </summary>
|
||
private GameObject LoadPrefabFromPackage(string prefabName)
|
||
{
|
||
// 优先从Package路径加载
|
||
string packagePath = $"Packages/com.yourcompany.threatsource/Runtime/Prefabs/{prefabName}";
|
||
var prefab = Resources.Load<GameObject>(packagePath);
|
||
|
||
if (prefab == null)
|
||
{
|
||
// 后备方案:从普通Resources加载
|
||
prefab = Resources.Load<GameObject>($"Prefabs/{prefabName}");
|
||
}
|
||
|
||
return prefab;
|
||
}
|
||
#endregion
|
||
|
||
#region 清理
|
||
/// <summary>
|
||
/// 清理Package
|
||
/// </summary>
|
||
private void CleanupPackage()
|
||
{
|
||
LogDebug("正在清理ThreatSource Package");
|
||
|
||
_simulationManager?.StopSimulation();
|
||
_simulationManager = null;
|
||
|
||
foreach (var gameObject in _entityGameObjects.Values)
|
||
{
|
||
if (gameObject != null)
|
||
{
|
||
Destroy(gameObject);
|
||
}
|
||
}
|
||
_entityGameObjects.Clear();
|
||
|
||
LogDebug("ThreatSource Package清理完成");
|
||
}
|
||
#endregion
|
||
|
||
#region 调试日志
|
||
private void LogDebug(string message)
|
||
{
|
||
if (enableDebugLogging)
|
||
{
|
||
Debug.Log($"[ThreatSourcePackage] {message}");
|
||
}
|
||
}
|
||
|
||
private void LogError(string message)
|
||
{
|
||
Debug.LogError($"[ThreatSourcePackage] {message}");
|
||
}
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// Package专用的导弹控制器
|
||
/// </summary>
|
||
public class PackageMissileController : MonoBehaviour
|
||
{
|
||
private string _missileId;
|
||
private string _targetId;
|
||
private TrailRenderer _trailRenderer;
|
||
private ParticleSystem _thrustEffect;
|
||
|
||
public void Initialize(string missileId, string targetId)
|
||
{
|
||
_missileId = missileId;
|
||
_targetId = targetId;
|
||
|
||
// 初始化组件
|
||
_trailRenderer = GetComponent<TrailRenderer>();
|
||
_thrustEffect = GetComponentInChildren<ParticleSystem>();
|
||
|
||
// 订阅Package事件
|
||
ThreatSourceEvents.Instance.OnFlightPhaseChanged += OnFlightPhaseChanged;
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
// 取消订阅
|
||
if (ThreatSourceEvents.Instance != null)
|
||
{
|
||
ThreatSourceEvents.Instance.OnFlightPhaseChanged -= OnFlightPhaseChanged;
|
||
}
|
||
}
|
||
|
||
private void OnFlightPhaseChanged(string missileId, FlightPhase newPhase)
|
||
{
|
||
if (missileId != _missileId) return;
|
||
|
||
switch (newPhase)
|
||
{
|
||
case FlightPhase.Boost:
|
||
if (_thrustEffect != null) _thrustEffect.Play();
|
||
break;
|
||
case FlightPhase.Midcourse:
|
||
if (_trailRenderer != null) _trailRenderer.enabled = true;
|
||
break;
|
||
case FlightPhase.Terminal:
|
||
if (_trailRenderer != null) _trailRenderer.material.color = Color.red;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Package事件系统
|
||
/// </summary>
|
||
public class ThreatSourceEvents : MonoBehaviour
|
||
{
|
||
private static ThreatSourceEvents _instance;
|
||
public static ThreatSourceEvents Instance
|
||
{
|
||
get
|
||
{
|
||
if (_instance == null)
|
||
{
|
||
_instance = FindObjectOfType<ThreatSourceEvents>();
|
||
if (_instance == null)
|
||
{
|
||
GameObject go = new GameObject("ThreatSourceEvents");
|
||
_instance = go.AddComponent<ThreatSourceEvents>();
|
||
DontDestroyOnLoad(go);
|
||
}
|
||
}
|
||
return _instance;
|
||
}
|
||
}
|
||
|
||
// Unity Events for Package users
|
||
public System.Action<string, string> OnMissileFired;
|
||
public System.Action<string, Vector3> OnMissileExploded;
|
||
public System.Action<string, FlightPhase> OnFlightPhaseChanged;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 坐标系转换工具(Package版本)
|
||
/// </summary>
|
||
public static class CoordinateConverter
|
||
{
|
||
public static Vector3 ThreatSourceToUnity(ThreatSource.Utils.Vector3D position)
|
||
{
|
||
return new Vector3(
|
||
(float)position.X,
|
||
(float)position.Z,
|
||
(float)position.Y
|
||
);
|
||
}
|
||
|
||
public static ThreatSource.Utils.Vector3D UnityToThreatSource(Vector3 position)
|
||
{
|
||
return new ThreatSource.Utils.Vector3D(
|
||
position.x,
|
||
position.z,
|
||
position.y
|
||
);
|
||
}
|
||
|
||
public static Quaternion OrientationToQuaternion(Orientation orientation)
|
||
{
|
||
return Quaternion.Euler(
|
||
(float)(orientation.Pitch * Mathf.Rad2Deg),
|
||
(float)(orientation.Yaw * Mathf.Rad2Deg),
|
||
(float)(orientation.Roll * Mathf.Rad2Deg)
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Package使用示例脚本
|
||
/// 展示如何在用户项目中使用ThreatSource Package
|
||
/// </summary>
|
||
namespace ThreatSourceUnity.Samples
|
||
{
|
||
using ThreatSourceUnity;
|
||
|
||
public class PackageExampleUsage : MonoBehaviour
|
||
{
|
||
[Header("示例配置")]
|
||
[SerializeField] private bool autoCreateScene = true;
|
||
[SerializeField] private float sceneCreationDelay = 2f;
|
||
|
||
private void Start()
|
||
{
|
||
if (autoCreateScene)
|
||
{
|
||
Invoke(nameof(CreateExampleScene), sceneCreationDelay);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建示例场景
|
||
/// </summary>
|
||
public void CreateExampleScene()
|
||
{
|
||
var packageManager = ThreatSourcePackageManager.Instance;
|
||
|
||
// 创建目标
|
||
string targetId = packageManager.CreateTarget(
|
||
"package_target_001",
|
||
new Vector3(1000, 0, 100),
|
||
new Vector3(-50, 0, 0)
|
||
);
|
||
|
||
// 创建导弹
|
||
string missileId = packageManager.CreateMissile(
|
||
"IR_Missile_Example",
|
||
Vector3.zero,
|
||
targetId
|
||
);
|
||
|
||
Debug.Log($"Package示例场景创建完成: 导弹 {missileId} -> 目标 {targetId}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 手动创建导弹
|
||
/// </summary>
|
||
public void CreateMissile()
|
||
{
|
||
var packageManager = ThreatSourcePackageManager.Instance;
|
||
packageManager.CreateMissile("IR_Missile_Example", transform.position, "package_target_001");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 订阅Package事件示例
|
||
/// </summary>
|
||
private void OnEnable()
|
||
{
|
||
ThreatSourceEvents.Instance.OnMissileFired += OnMissileFired;
|
||
ThreatSourceEvents.Instance.OnMissileExploded += OnMissileExploded;
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
if (ThreatSourceEvents.Instance != null)
|
||
{
|
||
ThreatSourceEvents.Instance.OnMissileFired -= OnMissileFired;
|
||
ThreatSourceEvents.Instance.OnMissileExploded -= OnMissileExploded;
|
||
}
|
||
}
|
||
|
||
private void OnMissileFired(string missileId, string targetId)
|
||
{
|
||
Debug.Log($"用户项目收到事件: 导弹 {missileId} 向 {targetId} 发射");
|
||
}
|
||
|
||
private void OnMissileExploded(string missileId, Vector3 position)
|
||
{
|
||
Debug.Log($"用户项目收到事件: 导弹 {missileId} 在 {position} 爆炸");
|
||
}
|
||
}
|
||
}
|
||
|
||
#endif // 结束编译指令块 |