您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
320 行
13 KiB
320 行
13 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using Unity.Collections;
|
|
using UnityEngine;
|
|
using Unity.Entities;
|
|
using UnityEngine.Analytics;
|
|
using UnityEngine.Assertions.Must;
|
|
|
|
public enum CameraMode
|
|
{
|
|
Undefined,
|
|
FirstPerson,
|
|
ThirdPerson,
|
|
FreeCam,
|
|
}
|
|
|
|
[RequireComponent(typeof(LocalPlayer))]
|
|
[RequireComponent(typeof(PlayerCameraSettings))]
|
|
public class LocalPlayerCharacterControl : MonoBehaviour
|
|
{
|
|
[ConfigVar(Name = "char.showhistory", DefaultValue = "0", Description = "Show last char loco states")]
|
|
public static ConfigVar ShowHistory;
|
|
|
|
public Entity lastRegisteredControlledEntity;
|
|
|
|
public CharacterHealthUI healthUI;
|
|
public IngameHUD hud;
|
|
|
|
public CameraMode cameraMode;
|
|
|
|
public int lastDamageInflictedTick;
|
|
public int lastDamageReceivedTick;
|
|
|
|
public List<AbilityUI> registeredCharUIs = new List<AbilityUI>();
|
|
|
|
public class FirstPersonData
|
|
{
|
|
public Entity char3P;
|
|
public Entity char1P;
|
|
public List<Entity> items = new List<Entity>();
|
|
}
|
|
|
|
public FirstPersonData firstPerson = new FirstPersonData();
|
|
}
|
|
|
|
|
|
[DisableAutoCreation]
|
|
public class UpdateCharacter1PSpawn : BaseComponentSystem
|
|
{
|
|
ComponentGroup Group;
|
|
ComponentGroup ItemGroup;
|
|
|
|
public UpdateCharacter1PSpawn(GameWorld world, BundledResourceManager resourceManager) : base(world)
|
|
{
|
|
m_ResourceManager = resourceManager;
|
|
}
|
|
|
|
protected override void OnCreateManager(int capacity)
|
|
{
|
|
base.OnCreateManager(capacity);
|
|
Group = GetComponentGroup(typeof(LocalPlayer), typeof(LocalPlayerCharacterControl));
|
|
ItemGroup = GetComponentGroup(typeof(CharacterItem));
|
|
}
|
|
|
|
|
|
private List<LocalPlayerCharacterControl> charControlBuffer = new List<LocalPlayerCharacterControl>(2);
|
|
private List<Entity> entityBuffer = new List<Entity>(2);
|
|
private List<Entity> itemEntityBuffer = new List<Entity>(8);
|
|
protected override void OnUpdate()
|
|
{
|
|
charControlBuffer.Clear();
|
|
entityBuffer.Clear();
|
|
var charControlArray = Group.GetComponentArray<LocalPlayerCharacterControl>();
|
|
var localPlayerArray = Group.GetComponentArray<LocalPlayer>();
|
|
for (var i = 0; i < charControlArray.Length; i++)
|
|
{
|
|
var localPlayer = localPlayerArray[i];
|
|
var characterControl = charControlArray[i];
|
|
|
|
var controlledChar3PEntity = EntityManager.Exists(localPlayer.controlledEntity) && EntityManager.HasComponent<CharacterPredictedState>(localPlayer.controlledEntity)
|
|
? localPlayer.controlledEntity
|
|
: Entity.Null;
|
|
|
|
if (characterControl.firstPerson.char3P != controlledChar3PEntity)
|
|
{
|
|
charControlBuffer.Add(characterControl);
|
|
entityBuffer.Add(controlledChar3PEntity);
|
|
}
|
|
}
|
|
|
|
if (charControlBuffer.Count > 0)
|
|
{
|
|
var itemArray = ItemGroup.GetComponentArray<CharacterItem>();
|
|
var itemEntityArray = ItemGroup.GetEntityArray();
|
|
|
|
for (var i = 0; i < charControlBuffer.Count; i++)
|
|
{
|
|
var charCtrl = charControlBuffer[i];
|
|
var charClientEntity = entityBuffer[i];
|
|
|
|
// Get items owned by character
|
|
itemEntityBuffer.Clear();
|
|
for (var j = 0; j < itemArray.Length; j++)
|
|
{
|
|
var item = itemArray[j];
|
|
if (item.character == charClientEntity)
|
|
itemEntityBuffer.Add(itemEntityArray[j]);
|
|
}
|
|
|
|
// Despawn current firstperson
|
|
if (charCtrl.firstPerson.char1P != Entity.Null)
|
|
{
|
|
GameDebug.Log("Despawning 1P char and items");
|
|
|
|
var go = EntityManager.GetComponentObject<Transform>(charCtrl.firstPerson.char1P).gameObject;
|
|
m_world.RequestDespawn(go, PostUpdateCommands);
|
|
|
|
|
|
foreach (var entity in charCtrl.firstPerson.items)
|
|
{
|
|
var item = EntityManager.GetComponentObject<Transform>(entity).gameObject;
|
|
|
|
// In preview mode the server code will despawn all items so we need to check it isnt already requested
|
|
if(!EntityManager.HasComponent<DespawningEntity>(entity))
|
|
m_world.RequestDespawn(item, PostUpdateCommands);
|
|
}
|
|
|
|
charCtrl.firstPerson.items.Clear();
|
|
charCtrl.firstPerson.char1P = Entity.Null;
|
|
}
|
|
|
|
charCtrl.firstPerson.char3P = charClientEntity;
|
|
|
|
|
|
|
|
|
|
// Spawn new
|
|
if (charClientEntity != Entity.Null)
|
|
{
|
|
GameDebug.Log("Spawning 1P char and items");
|
|
|
|
|
|
// Create 1P character
|
|
{
|
|
var replicatedEntity = EntityManager.GetComponentObject<ReplicatedEntity>(charClientEntity);
|
|
var registry = m_ResourceManager.GetResourceRegistry<CharacterTypeRegistry>();
|
|
var registryIndex = registry.GetIndexByClientGUID(replicatedEntity.guid);
|
|
GameDebug.Assert(registryIndex != -1);
|
|
var char1PGUID = registry.entries[registryIndex].prefab1P.guid;
|
|
if (char1PGUID != "")
|
|
{
|
|
var prefab1P = m_ResourceManager.LoadSingleAssetResource(char1PGUID) as GameObject;
|
|
var gameObjectEntity = m_world.Spawn<GameObjectEntity>(prefab1P);
|
|
var char1P = EntityManager.GetComponentObject<Character1P>(gameObjectEntity.Entity);
|
|
char1P.character = charClientEntity;
|
|
charCtrl.firstPerson.char1P = gameObjectEntity.Entity;
|
|
}
|
|
}
|
|
|
|
// Create 1P items
|
|
{
|
|
for (var j = 0; j < itemEntityBuffer.Count; j++)
|
|
{
|
|
var itemEntity = itemEntityBuffer[j];
|
|
|
|
var replicatedEntity = EntityManager.GetComponentObject<ReplicatedEntity>(itemEntity);
|
|
var itemGUID = replicatedEntity.guid;
|
|
var itemRegistry = m_ResourceManager.GetResourceRegistry<ItemRegistry>();
|
|
var itemDefIndex = itemRegistry.GetIndexByClientGUID(itemGUID);
|
|
if (itemDefIndex != -1)
|
|
{
|
|
var item1PGUID = itemRegistry.entries[itemDefIndex].prefab1P.guid;
|
|
if (item1PGUID != "")
|
|
{
|
|
var itemPrefab1P = m_ResourceManager.LoadSingleAssetResource(item1PGUID) as GameObject;
|
|
var gameObejctEntity = m_world.Spawn<GameObjectEntity>(itemPrefab1P);
|
|
|
|
var item = EntityManager.GetComponentObject<CharacterItem>(gameObejctEntity.Entity);
|
|
item.character = charClientEntity;
|
|
|
|
var item1P = EntityManager.GetComponentObject<CharacterItem1P>(gameObejctEntity.Entity);
|
|
item1P.item = itemEntity;
|
|
item1P.character1P = charCtrl.firstPerson.char1P;
|
|
|
|
|
|
|
|
charCtrl.firstPerson.items.Add(gameObejctEntity.Entity);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BundledResourceManager m_ResourceManager;
|
|
}
|
|
|
|
|
|
|
|
|
|
[DisableAutoCreation]
|
|
public class UpdateCharacterCamera : BaseComponentSystem<LocalPlayer,LocalPlayerCharacterControl,PlayerCameraSettings>
|
|
{
|
|
public UpdateCharacterCamera(GameWorld world) : base(world) {}
|
|
|
|
public void ToggleFOrceThirdPerson()
|
|
{
|
|
forceThirdPerson = !forceThirdPerson;
|
|
}
|
|
|
|
protected override void Update(Entity entity, LocalPlayer localPlayer, LocalPlayerCharacterControl characterControl, PlayerCameraSettings cameraSettings)
|
|
{
|
|
if (localPlayer.controlledEntity == Entity.Null || !EntityManager.HasComponent<CharacterPredictedState>(localPlayer.controlledEntity))
|
|
{
|
|
controlledEntity = Entity.Null;
|
|
return;
|
|
}
|
|
|
|
if (characterControl.firstPerson.char1P == Entity.Null)
|
|
{
|
|
controlledEntity = Entity.Null;
|
|
return;
|
|
}
|
|
|
|
GameDebug.Assert(EntityManager.HasComponent<CharAnimState>(localPlayer.controlledEntity),"Controlled entity has no animstate");
|
|
|
|
var character = EntityManager.GetComponentObject<Character>(localPlayer.controlledEntity);
|
|
var charPredictedState = EntityManager.GetComponentObject<CharacterPredictedState>(localPlayer.controlledEntity);
|
|
|
|
var animState = EntityManager.GetComponentData<CharAnimState>(localPlayer.controlledEntity);
|
|
var character1P = EntityManager.GetComponentObject<Character1P>(characterControl.firstPerson.char1P);
|
|
|
|
// Check if this is first time update is called with this controlled entity
|
|
var characterChanged = localPlayer.controlledEntity != controlledEntity;
|
|
if (characterChanged)
|
|
{
|
|
controlledEntity = localPlayer.controlledEntity;
|
|
|
|
}
|
|
|
|
// Update camera mode
|
|
var newCamMode = CameraMode.FreeCam;
|
|
if (charPredictedState != null)
|
|
{
|
|
var characterEntity = charPredictedState.gameObject.GetComponent<GameObjectEntity>().Entity;
|
|
var healthState = EntityManager.GetComponentObject<HealthState>(characterEntity);
|
|
var isAlive = healthState.health > 0;
|
|
newCamMode = isAlive ? CameraMode.FirstPerson : CameraMode.ThirdPerson;
|
|
}
|
|
if (forceThirdPerson)
|
|
{
|
|
newCamMode = CameraMode.ThirdPerson;
|
|
}
|
|
characterControl.cameraMode = newCamMode;
|
|
|
|
|
|
// Update character visibility
|
|
var thirdPerson = characterControl.cameraMode == CameraMode.ThirdPerson;
|
|
|
|
character.isVisible = thirdPerson;
|
|
character1P.isVisible = !thirdPerson;
|
|
|
|
// Update camera settings
|
|
var userCommand = EntityManager.GetComponentObject<UserCommandComponent>(localPlayer.controlledEntity);
|
|
var lookRotation = userCommand.command.lookRotation;
|
|
|
|
cameraSettings.isEnabled = true;
|
|
|
|
// Update FOV
|
|
if(characterChanged)
|
|
cameraSettings.fieldOfView = Game.configFov.FloatValue;
|
|
var settings = character.heroTypeData.sprintCameraSettings;
|
|
var targetFOV = animState.sprinting == 1 ? settings.FOVFactor* Game.configFov.FloatValue : Game.configFov.FloatValue;
|
|
var speed = targetFOV > cameraSettings.fieldOfView ? settings.FOVInceraetSpeed : settings.FOVDecreaseSpeed;
|
|
cameraSettings.fieldOfView = Mathf.MoveTowards(cameraSettings.fieldOfView, targetFOV, speed);
|
|
|
|
switch (characterControl.cameraMode)
|
|
{
|
|
case CameraMode.FirstPerson:
|
|
|
|
// Set camera position and adjust 1P char. As 1P char is scaled we need to "up-scale" camera
|
|
// animation to world space and adjust char1P position accordingly
|
|
var camLocalOffset = character1P.cameraTransform.position - character1P.transform.position;
|
|
var camWorldOffset = camLocalOffset/character1P.transform.localScale.x;
|
|
var camWorldPos = character1P.transform.position + camWorldOffset;
|
|
var charWorldPos = camWorldPos - camLocalOffset;
|
|
|
|
cameraSettings.position = camWorldPos;
|
|
cameraSettings.rotation = character1P.cameraTransform.rotation; //lookRotation * cameraRotationOffset;
|
|
|
|
character1P.transform.position = charWorldPos;
|
|
|
|
|
|
break;
|
|
case CameraMode.ThirdPerson:
|
|
var eyePos = charPredictedState.State.position + Vector3.up*character.eyeHeight;
|
|
cameraSettings.position = eyePos;
|
|
cameraSettings.rotation = lookRotation;
|
|
|
|
// Simpe offset of camera for better 3rd person view. This is only for animation debug atm
|
|
var viewDir = cameraSettings.rotation * Vector3.forward;
|
|
cameraSettings.position += -2.5f * viewDir;
|
|
cameraSettings.position += lookRotation*Vector3.right*0.5f + lookRotation*Vector3.up*0.5f;
|
|
break;
|
|
}
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
if (LocalPlayerCharacterControl.ShowHistory.IntValue > 0)
|
|
{
|
|
charPredictedState.ShowHistory(m_world);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
bool forceThirdPerson;
|
|
Entity controlledEntity;
|
|
}
|