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

344 行
14 KiB

using System.Collections.Generic;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Physics;
using Unity.Physics.Systems;
using UnityEngine;
[DisableAutoCreation]
[AlwaysUpdateSystem]
public class UpdateCharacterUI : ComponentSystem
{
private IngameHUD m_Hud;
private NamePlate m_NamePlate;
private List<NamePlate> m_NamePlates = new List<NamePlate>();
public struct NamePlateEntityHolder : ISystemStateComponentData
{
public int namePlateIdx;
}
protected override void OnCreate()
{
m_Hud = Resources.Load<IngameHUD>("Prefabs/CharacterHUD");
m_NamePlate = Resources.Load<NamePlate>("Prefabs/NamePlate");
}
protected override void OnUpdate()
{
// Create and update health UI
int self_id = -1;
int selfTeamIdx = -1;
Entities.ForEach((Entity e, ref LocalPlayer localPlayer) =>
{
self_id = localPlayer.playerId;
if(localPlayer.hudEntity == Entity.Null)
localPlayer.hudEntity = PrefabAssetManager.CreateEntity(EntityManager.World, m_Hud.gameObject);
if(localPlayer.controlledEntity != Entity.Null)
{
var h = EntityManager.GetComponentData<HealthStateData>(localPlayer.controlledEntity);
var hud = EntityManager.GetComponentObject<IngameHUD>(localPlayer.hudEntity);
hud.FrameUpdate();
hud.m_Health.UpdateUI(ref h);
}
// Store our team idx for nameplate coloring below
if(EntityManager.Exists(localPlayer.playerEntity))
{
var ps = EntityManager.GetComponentData<Player.State>(localPlayer.playerEntity);
selfTeamIdx = ps.teamIndex;
}
});
// Create nameplate for new players
Entities.WithNone<NamePlateEntityHolder>().ForEach((Entity e, ref Player.State player) =>
{
if (player.playerId == self_id)
return;
var npe = new NamePlateEntityHolder();
var avail = m_NamePlates.IndexOf(null);
if(avail < 0)
{
avail = m_NamePlates.Count;
m_NamePlates.Add(null);
}
npe.namePlateIdx = avail;
m_NamePlates[avail] = GameObject.Instantiate<NamePlate>(m_NamePlate);
EntityManager.AddComponentData(e, npe);
});
// Destroy nameplate for players gone
Entities.WithNone<Player.State>().ForEach((Entity e, ref NamePlateEntityHolder namePlateEntity) =>
{
GameObject.Destroy(m_NamePlates[namePlateEntity.namePlateIdx]);
m_NamePlates[namePlateEntity.namePlateIdx] = null;
EntityManager.RemoveComponent(e, typeof(NamePlateEntityHolder));
});
var physicsWorldSystem = World.GetExistingSystem<BuildPhysicsWorld>();
// Update nameplates
Entities.ForEach((Entity e, ref Player.State player, ref NamePlateEntityHolder plateHolder) =>
{
// Skip players not controlling anything
if (player.controlledEntity == Entity.Null)
return;
// Skip self
if (player.playerId == self_id)
return;
// Only if controlling somethin with pos
if (!EntityManager.HasComponent<Unity.Transforms.LocalToWorld>(player.controlledEntity))
return;
// Get screenpos
var ltw = EntityManager.GetComponentData<Unity.Transforms.LocalToWorld>(player.controlledEntity);
var camera = GameApp.CameraStack.TopCamera();
var platePos = ltw.Position + new float3(0, 1.8f, 0);
var screenPos = camera.WorldToScreenPoint(platePos);
var namePlate = m_NamePlates[plateHolder.namePlateIdx];
// Update visibility
bool visible = screenPos.z > 0;
if(visible)
{
// Check for occlusion
var rayStart = camera.ScreenToWorldPoint(new Vector3(screenPos.x, screenPos.y, 0));
var filter = CollisionFilter.Default;
filter.CollidesWith = 1 << 0;
var ray = new RaycastInput()
{
Start = rayStart,
End = platePos,
Filter = filter
};
Unity.Physics.RaycastHit hit;
if (physicsWorldSystem.PhysicsWorld.CollisionWorld.CastRay(ray, out hit))
{
visible = false;
}
}
if (!visible && namePlate.gameObject.activeSelf)
namePlate.gameObject.SetActive(false);
else if (visible && !namePlate.gameObject.activeSelf)
namePlate.gameObject.SetActive(true);
if (!visible)
return;
var friendly = player.teamIndex == selfTeamIdx;
// Update position and name and color
namePlate.namePlateRoot.transform.position = screenPos;
namePlate.nameText.Set(ref player.playerName);
namePlate.nameText.color = Game.game.gameColors[friendly ? (int)Game.GameColor.Friend : (int)Game.GameColor.Enemy];
});
}
protected override void OnDestroy()
{
Entities.ForEach((Entity e, ref LocalPlayer lp) =>
{
if(lp.hudEntity != Entity.Null)
PrefabAssetManager.DestroyEntity(EntityManager, lp.hudEntity);
});
foreach(var e in m_NamePlates)
{
if (e != null)
GameObject.Destroy(e);
}
}
}
// TODO: mogensh I disabled this out when removing presentationentity
//[DisableAutoCreation]
//public class UpdateCharacterUI : BaseComponentSystem
//{
// EntityQuery Group;
// Entity hud;
//
// public UpdateCharacterUI(GameWorld world) : base(world)
// {
// m_prefab = Resources.Load<IngameHUD>("Prefabs/CharacterHUD");
// }
//
// protected override void OnCreate()
// {
// base.OnCreate();
// Group = GetEntityQuery(typeof(LocalPlayer), typeof(PlayerCameraSettings.State),
// typeof(LocalPlayerCharacterControl.State));
//
// hud = PrefabAssetManager.CreateEntity(World, m_prefab.gameObject);
// }
//
// protected override void OnDestroy()
// {
// PrefabAssetManager.DestroyEntity(EntityManager, hud);
// }
//
// protected override void OnUpdate()
// {
// var entityArray = Group.ToEntityArray(Allocator.TempJob);
// var localPlayerArray = Group.ToComponentArray<LocalPlayer>();
// var playerCamSettingsArray = Group.ToComponentDataArray<PlayerCameraSettings.State>(Allocator.TempJob);
// var charControlArray = Group.ToComponentDataArray<LocalPlayerCharacterControl.State>(Allocator.TempJob);
//
// GameDebug.Assert(localPlayerArray.Length <= 1, "There should never be more than 1 local player!");
//
// for (var i = 0; i < localPlayerArray.Length; i++)
// {
// var entity = entityArray[i];
// var localPlayer = localPlayerArray[i];
// var characterControl = charControlArray[i];
// var cameraSettings = playerCamSettingsArray[i];
//
// var ingameHUD = EntityManager.GetComponentObject<IngameHUD>(hud);
//
// // Handle controlled entity change
// if (characterControl.lastRegisteredControlledEntity != localPlayer.controlledEntity)
// {
// // Delete all current UI elements
// if (characterControl.healthUI != Entity.Null)
// {
// PrefabAssetManager.DestroyEntity(EntityManager,characterControl.healthUI);
// }
// characterControl.healthUI = Entity.Null;
//
// {
// var abilityUIBuffer = EntityManager.GetBuffer<LocalPlayerCharacterControl.AbilityUIElement>(entity).ToNativeArray(Allocator.Temp);
// EntityManager.GetBuffer<LocalPlayerCharacterControl.AbilityUIElement>(entity).Clear();
// for (var j = 0; j < abilityUIBuffer.Length; j++)
// {
// PrefabAssetManager.DestroyEntity(EntityManager,abilityUIBuffer[j].entity);
// }
// }
//
// //
// characterControl.lastRegisteredControlledEntity = Entity.Null;
//
// // Set new controlled entity
// if (EntityManager.HasComponent<Character.State>(localPlayer.controlledEntity))
// {
// characterControl.lastRegisteredControlledEntity = localPlayer.controlledEntity;
// }
//
//
// // Build new UI elements
// if (characterControl.lastRegisteredControlledEntity != Entity.Null &&
// EntityManager.Exists(characterControl.lastRegisteredControlledEntity))
// {
// var characterEntity = characterControl.lastRegisteredControlledEntity;
//
// if (EntityManager.HasComponent<PresentationOwner.State>(characterEntity))
// {
// var presentationOwner =
// EntityManager.GetComponentData<PresentationOwner.State>(characterEntity);
//
// var charPresentation = presentationOwner.currentPresentation;
//
// if (EntityManager.HasComponent<CharacterUISetup>(charPresentation))
// {
// // TODO (mogensh) we should move UI setup out to Hero setup (or something similar clientside)
// var uiSetup = EntityManager.GetComponentObject<CharacterUISetup>(charPresentation);
// if (uiSetup.healthUIPrefab != null)
// {
// characterControl.healthUI =
// PrefabAssetManager.CreateEntity(World, uiSetup.healthUIPrefab.gameObject);
//
// var healthUI =
// EntityManager.GetComponentObject<CharacterHealthUI>(characterControl.healthUI);
//
// healthUI.transform.SetParent(ingameHUD.transform, false);
// }
// }
//
// // TODO (mogensh) this has moved to PresentationUI. But this UI is a mess and needs to be rethought
//// var presentationsBuffer = EntityManager.GetBuffer<Character.Presentation>(characterEntity).ToNativeArray(Allocator.Temp);
//// for (int j = 0; j < presentationsBuffer.Length; j++)
//// {
//// var presentationEntity = presentationsBuffer[j].entity;
//// if (EntityManager.HasComponent<CharacterPresentationSetup>(presentationEntity))
//// {
//// var charPresSetup = EntityManager.GetComponentObject<CharacterPresentationSetup>(presentationEntity);
////
//// if (charPresSetup.uiPrefabs == null || charPresSetup.uiPrefabs.Length == 0)
//// continue;
////
//// foreach (var uiPrefab in charPresSetup.uiPrefabs)
//// {
//// var abilityUIEntity = PrefabAssetManager.CreateEntity(World, uiPrefab.gameObject);
//// var abilityUI = EntityManager.GetComponentData<AbilityUI.State>(abilityUIEntity);
//// abilityUI.abilityOwner = characterEntity;
//// EntityManager.SetComponentData(abilityUIEntity,abilityUI);
////
//// var transform = EntityManager.GetComponentObject<RectTransform>(abilityUIEntity);
//// transform.SetParent(ingameHUD.transform, false);
////
//// var abilityUIBuffer = EntityManager.GetBuffer<LocalPlayerCharacterControl.AbilityUIElement>(entity);
//// abilityUIBuffer.Add(new LocalPlayerCharacterControl.AbilityUIElement
//// {
//// entity = abilityUIEntity
//// });
//// }
//// }
//// }
//// presentationsBuffer.Dispose();
// }
// }
// }
//
//
// // Update current setup
// if (characterControl.lastRegisteredControlledEntity == Entity.Null)
// continue;
//
// // Check for damage inflicted and recieved
// var damageHistory = EntityManager.GetComponentData<DamageHistoryData>(characterControl.lastRegisteredControlledEntity);
// if (damageHistory.inflictedDamage.tick > characterControl.lastDamageInflictedTick)
// {
// characterControl.lastDamageInflictedTick = damageHistory.inflictedDamage.tick;
// ingameHUD.ShowHitMarker(damageHistory.inflictedDamage.lethal == 1);
// }
//
// var charAnimState =
// EntityManager.GetComponentData<Character.InterpolatedData>(characterControl
// .lastRegisteredControlledEntity);
// if (charAnimState.damageTick > characterControl.lastDamageReceivedTick)
// {
// ingameHUD.m_Crosshair.ShowHitDirectionIndicator(charAnimState.damageDirection);
// characterControl.lastDamageReceivedTick = charAnimState.damageTick;
// }
//
// // Update health
// if (characterControl.healthUI != Entity.Null)
// {
// var healthState = EntityManager.GetComponentData<HealthStateData>(characterControl.lastRegisteredControlledEntity);
//
// var healthUI =
// EntityManager.GetComponentObject<CharacterHealthUI>(characterControl.healthUI);
//
// healthUI.UpdateUI(ref healthState);
// }
//
// var playerState = EntityManager.GetComponentData<Player.State>(localPlayer.playerEntity);
// ingameHUD.FrameUpdate(ref playerState, cameraSettings);
//
// EntityManager.SetComponentData(entity,characterControl);
//
// }
//
// entityArray.Dispose();
// charControlArray.Dispose();
// playerCamSettingsArray.Dispose();
// }
//
// IngameHUD m_prefab;
//}