You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
4.2 KiB

1 month ago
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using CoreGame;
using UnityEngine;
namespace CoreGame.Render
{
public static class ColliderSrv
{
private static readonly Dictionary<Collider2D, int> s_ColliderMap = new Dictionary<Collider2D, int>();
private static readonly int s_PlayerLayer = LayerMask.NameToLayer("Player");
private static readonly int s_EnemyLayer = LayerMask.NameToLayer("Enemy");
public static readonly int s_ObstacleLayer = LayerMask.NameToLayer("Obstacle");
private static int[] s_PlayerCollisionMasks;
private static int[] s_EnemyCollisionMasks;
public static void Init()
{
s_ColliderMap.Clear();
InitCollisionMasks();
}
private static void InitCollisionMasks()
{
const int maxConditions = 1 << 3; //2^3 三种碰撞条件,敌方,友方,障碍物,可能会添加
s_PlayerCollisionMasks = new int[maxConditions];
s_EnemyCollisionMasks = new int[maxConditions];
for (var i = 0; i < maxConditions; i++)
{
s_PlayerCollisionMasks[i] = CalculateLayerMask(s_PlayerLayer, s_EnemyLayer, i);
s_EnemyCollisionMasks[i] = CalculateLayerMask(s_EnemyLayer, s_PlayerLayer, i);
}
}
private static int CalculateLayerMask(int sameLayer, int oppositeLayer, int collideWith)
{
var mask = 0;
var sameLayerMask = 1 << sameLayer;
var oppositeLayerMask = 1 << oppositeLayer;
var obstacleLayerMask = 1 << s_ObstacleLayer;
if ((collideWith & 1) != 0) // 敌方
mask |= oppositeLayerMask;
if ((collideWith & 2) != 0) // 友方
mask |= sameLayerMask;
if ((collideWith & 4) != 0) // 建筑物
mask |= obstacleLayerMask;
return mask == 0 ? LayerMask.GetMask("Default") : mask;
}
/// <summary>
/// 碰撞LayerMask
/// </summary>
/// <param name="faction">自己所在阵营</param>
/// <param name="collideWith">碰撞参数掩码,1-敌方,2-友方,4-建筑物</param>
/// <returns></returns>
public static LayerMask GetLayerMask(Faction faction, int collideWith)
{
return faction switch
{
Faction.Player => s_PlayerCollisionMasks[collideWith],
Faction.Enemy => s_EnemyCollisionMasks[collideWith],
_ => LayerMask.GetMask("Default")
};
}
public static int GetLayer(Faction faction)
{
if (faction == Faction.Player)
return s_PlayerLayer;
if (faction == Faction.Enemy)
return s_EnemyLayer;
return LayerMask.NameToLayer("Default");
}
public static void AddCollider(Collider2D collider, int eid)
{
if (!s_ColliderMap.TryAdd(collider, eid))
{
BattleLogger.LogInfo("ColliderSrv AddCollider failed");
}
}
public static void RemoveCollider(Collider2D collider)
{
if (!s_ColliderMap.Remove(collider))
{
BattleLogger.LogInfo("ColliderSrv RemoveCollider failed");
}
}
public static void DisableCollider(Collider2D collider)
{
if (!s_ColliderMap.ContainsKey(collider))
{
BattleLogger.LogInfo("ColliderSrv DisableCollider failed");
}
collider.enabled = false;
}
public static void EnableCollider(Collider2D collider)
{
if (!s_ColliderMap.ContainsKey(collider))
{
BattleLogger.LogInfo("ColliderSrv EnableCollider failed");
}
collider.enabled = true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static CombatEntity GetEntityByCollider(Collider2D collider)
{
if (s_ColliderMap.TryGetValue(collider, out int eid))
{
return (CombatEntity)Contexts.Combat.GetEntity(eid);
}
return null;
}
}
}