您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

269 行
8.5 KiB

using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.CompilerServices;
using System.Xml.Schema;
using Unity.Entities;
using Unity.Properties;
using UnityEngine;
public struct CharacterAbility : IComponentData
{
public Entity character;
}
public struct AbilityControl : IPredictedData<AbilityControl>, IComponentData
{
public int activeAllowed;
public int requestsActive;
public void Serialize(ref NetworkWriter writer, IEntityReferenceSerializer refSerializer)
{
writer.WriteBoolean("activeAllowed", activeAllowed == 1);
writer.WriteBoolean("requestsActive", requestsActive == 1);
}
public void Deserialize(ref NetworkReader reader, IEntityReferenceSerializer refSerializer, int tick)
{
activeAllowed = reader.ReadBoolean() ? 1 : 0;
requestsActive = reader.ReadBoolean() ? 1 : 0;
}
#if UNITY_EDITOR
public bool VerifyPrediction(ref AbilityControl state)
{
return true;
}
public override string ToString()
{
return "AbilityControl activeAllowed:" + activeAllowed + " requestActive:" + requestsActive;
}
#endif
}
public class AbilityController : MonoBehaviour, INetworkSerializable
{
[NonSerialized] public Entity[] abilityEntities = new Entity[8];
[NonSerialized] public int activeAbility = -1;
[NonSerialized] public int lastServerActiveAbility = -1;
public Entity GetAbilityEntity(EntityManager entityManager, Type abilityType)
{
for (var i = 0; i < abilityEntities.Length; i++)
{
var entity = abilityEntities[i];
if (entity == Entity.Null)
continue;
if (entityManager.HasComponent(entity, abilityType))
return entity;
}
return Entity.Null;
}
public void Serialize(ref NetworkWriter writer, IEntityReferenceSerializer refSerializer)
{
writer.SetFieldSection(NetworkWriter.FieldSectionType.OnlyPredicting);
writer.WriteInt16("activeAbility",(short)activeAbility);
writer.ClearFieldSection();
for (var i = 0; i < abilityEntities.Length; i++)
{
refSerializer.SerializeReference(ref writer, "ability", abilityEntities[i]);
}
}
public void Deserialize(ref NetworkReader reader, IEntityReferenceSerializer refSerializer, int tick)
{
lastServerActiveAbility = reader.ReadInt16();
activeAbility = lastServerActiveAbility;
for (var i = 0; i < abilityEntities.Length; i++)
{
var entity = Entity.Null;
refSerializer.DeserializeReference(ref reader, ref entity);
abilityEntities[i] = entity;
}
}
public void Rollback()
{
activeAbility = lastServerActiveAbility;
}
}
[DisableAutoCreation]
public class AbilityCtrl_UpdateServerEntityComponent : BaseComponentSystem
{
public struct GroupType
{
public EntityArray entities;
public ComponentArray<AbilityController> abilityControllers;
}
[Inject]
public GroupType Group;
public AbilityCtrl_UpdateServerEntityComponent(GameWorld world) : base(world) {}
protected override void OnUpdate()
{
for (var i = 0; i < Group.abilityControllers.Length; i++)
{
var abilityCtrl = Group.abilityControllers[i];
if (abilityCtrl.abilityEntities == null)
continue;
var abilityCtrlEntity = Group.entities[i];
var predicted = EntityManager.HasComponent<ServerEntity>(abilityCtrlEntity);
for (var j = 0; j < abilityCtrl.abilityEntities.Length; j++)
{
var ability = abilityCtrl.abilityEntities[j];
if (ability == Entity.Null)
continue;
if (EntityManager.HasComponent<ServerEntity>(ability) != predicted)
{
if(predicted)
PostUpdateCommands.AddComponent(ability, new ServerEntity());
else
PostUpdateCommands.RemoveComponent<ServerEntity>(ability);
}
}
}
}
}
[DisableAutoCreation]
[AlwaysUpdateSystem]
public class AbilityCtrl_HandleSpawn : InitializeComponentSystem<AbilityController>
{
public AbilityCtrl_HandleSpawn(GameWorld world) : base(world) {}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected override void Initialize(Entity entity, AbilityController component)
{
// Set character as owner of abilities
for (var i = 0; i < component.abilityEntities.Length; i++)
{
var abilityEntity = component.abilityEntities[i];
if (abilityEntity == Entity.Null)
continue;
var gameObjectEntity = component.GetComponent<GameObjectEntity>();
var charAbility = EntityManager.GetComponentData<CharacterAbility>(abilityEntity);
charAbility.character = gameObjectEntity.Entity;
EntityManager.SetComponentData(abilityEntity,charAbility);
}
}
}
[DisableAutoCreation]
public class AbilityCtrl_Update : BaseComponentSystem
{
ComponentGroup Group;
public AbilityCtrl_Update(GameWorld world) : base(world) {}
protected override void OnCreateManager(int capacity)
{
base.OnCreateManager(capacity);
Group = GetComponentGroup(typeof(ServerEntity), typeof(AbilityController));
}
protected override void OnUpdate()
{
var entityArray = Group.GetEntityArray();
var abilityControllerArray = Group.GetComponentArray<AbilityController>();
for (var i = 0; i < entityArray.Length; i++)
{
var abilityController = abilityControllerArray[i];
if (abilityController.abilityEntities == null)
continue;
var abilityControllerEntity = entityArray[i];
// Handle command
var requestedAbility = -1;
for (var j = 0; j < abilityController.abilityEntities.Length; j++)
{
var abilityEntity = abilityController.abilityEntities[j];
if (abilityEntity == Entity.Null)
continue;
var isActive = j == abilityController.activeAbility;
var ability = EntityManager.GetComponentData<AbilityControl>(abilityEntity);
var requestActive = ability.requestsActive == 1;
if(requestActive)
{
// TODO we simply select last that is requested. We need to setup conditions
requestedAbility = j;
if(isActive)
break;
}
}
if (requestedAbility != abilityController.activeAbility)
{
if (abilityController.activeAbility != -1)
{
var abilityEntity = abilityController.abilityEntities[abilityController.activeAbility];
var ability = EntityManager.GetComponentData<AbilityControl>(abilityEntity);
ability.activeAllowed = 0;
EntityManager.SetComponentData(abilityEntity,ability);
}
abilityController.activeAbility = requestedAbility;
if (abilityController.activeAbility != -1)
{
var abilityEntity = abilityController.abilityEntities[abilityController.activeAbility];
var ability = EntityManager.GetComponentData<AbilityControl>(abilityEntity);
ability.activeAllowed = 1;
EntityManager.SetComponentData(abilityEntity,ability);
}
var character = EntityManager.GetComponentObject<CharacterPredictedState>(abilityControllerEntity);
character.State.abilityActive = abilityController.activeAbility != -1;
}
}
}
}
[DisableAutoCreation]
public class AbilityCtrl_Rollback : ComponentSystem
{
public struct GroupType
{
public ComponentDataArray<ServerEntity> serverBehavior;
public ComponentArray<AbilityController> abilityController;
}
[Inject]
public GroupType Group;
public AbilityCtrl_Rollback(GameWorld gameWorld)
{
}
protected override void OnUpdate()
{
for (var i = 0; i < Group.abilityController.Length; i++)
{
Group.abilityController[i].Rollback();
}
}
}