private void Awake()
{
Instance = this;
this.InitializeAim();
}
private void Update()
{
this.UpdateAim();
}
/// <summary>
/// 初始化自瞄
/// </summary>
private void InitializeAim()
{
this.AllTargets = new List<IPlayerWeaponTarget>();
GameMessenger.AddEventListener<IPlayerWeaponTarget>("PWTSpawned", delegate (IPlayerWeaponTarget t)
{
this.AllTargets.Add(t);
});
GameMessenger.AddEventListener<IPlayerWeaponTarget>("PWTDespawned", delegate (IPlayerWeaponTarget t)
{
this.AllTargets.Remove(t);
});
}
/// <summary>
/// 更新目标
/// </summary>
private void UpdateAim()
{
//判断下是否拥有武器
if (!this.HasCurrentWeapon)
{
return;
}
//判断下List是否有元素
if (!this.AllTargets.Any<IPlayerWeaponTarget>())
{ //当前的目标为空
this.CurrentAimTarget = null;
return;
}
this.CurrentAimTarget = null;
float num = 0f;
//遍历list里的目标
for (int i = 0; i < this.AllTargets.Count; i++)
{
IPlayerWeaponTarget playerWeaponTarget = this.AllTargets[i];
//获得与玩家的距离
float approximateDistanceFromPlayer = playerWeaponTarget.GetApproximateDistanceFromPlayer();
//是否在玩家前面
if (playerWeaponTarget.IsAheadFromPlayer()
&& playerWeaponTarget.CamAimTo()
//获取目标和目标圆之间的平方距离 小于瞄准圆屏幕位置
&& this.GetSqrMagnitudeBetweenTargetAndAimCircle(playerWeaponTarget) < this.AimCircleRadiusAbsoluteSqr
//最大瞄准距离大于与玩家的距离
&& this.CurrentWeapon.MaxAimDistance > approximateDistanceFromPlayer
//当前目标 或者玩家的距离小于0
&& (this.CurrentAimTarget == null || approximateDistanceFromPlayer < num))
{ //当前的目标等于 获取目标 tram
this.CurrentAimTarget = playerWeaponTarget.GetPlayerAimTarget();
//跟新最近距离
num = approximateDistanceFromPlayer;
}
}
}
/// <summary>
/// 瞄准圆屏幕位置
/// </summary>
public Vector2 AimCircleScreenPosition
{
get
{
float num = (float)PlayerMainCameraSystem.Instance.MainCamera.pixelWidth / 2f;
float y = (float)PlayerMainCameraSystem.Instance.MainCamera.pixelHeight / 2f;
float num2 = 0f;
if (PlayerMovementSystem.Instance.XMovementState != PlayerMovementSystem.PlayerXMovementState.None)
{
num2 = (float)((PlayerMovementSystem.Instance.XMovementState == PlayerMovementSystem.PlayerXMovementState.MoveLeft) ? -1 : 1) * (this.GetAbsoluteWidthForAim(this.AimCircleMaxCenterOffset) * PlayerInputSystem.Instance.CurrentDirectionGestureXMultiplier);
}
return new Vector2(num + num2, y);
}
}
/// <summary>
/// 获取目标和目标圆之间的平方距离
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
private float GetSqrMagnitudeBetweenTargetAndAimCircle(IPlayerWeaponTarget target)
{
Vector2 aimTargetScreenSpacePosition = target.GetAimTargetScreenSpacePosition();
return (this.AimCircleScreenPosition - aimTargetScreenSpacePosition).sqrMagnitude;
}
/// <summary>
/// 获取范围内的目标
/// </summary>
/// <param name="origin"></param>
/// <param name="r"></param>
/// <returns></returns>
public IEnumerable<IPlayerWeaponTarget> GetTargetsInRange(Vector3 origin, float r)
{
float rr = r * r;
return from t in this.AllTargets
where (t.GetPlayerAimTarget().position - origin).sqrMagnitude < rr
select t;
}
/// <summary>
/// 处理武器射击
/// </summary>
private void HandleWeaponFire()
{ //调度武器伤害
this.DispatchWeaponDamage(this.CurrentAimTarget);
if (this.CurrentWeapon.MultikillRadius > 0f && this.CurrentAimTarget != null)
{
IEnumerable<IPlayerWeaponTarget> enumerable =
from t in this.AllTargets
where t.GetPlayerAimTarget() != this.CurrentAimTarget &&
(t.GetPlayerAimTarget().position - this.CurrentAimTarget.position).sqrMagnitude
< this.CurrentWeapon.MultikillRadius * this.CurrentWeapon.MultikillRadius
select t;
int num = 0;
foreach (IPlayerWeaponTarget playerWeaponTarget in enumerable)
{
if (num > this.CurrentWeapon.MaxMultikills)
{
break;
}
this.DispatchWeaponDamage(playerWeaponTarget.GetPlayerAimTarget());
num++;
}
}
if (!this.IsFiredInThisRun)
{
this.IsFiredInThisRun = true;
Debug.Log("PlayerFirstFireInRun");
}
}
/// <summary>
/// 调度武器伤害
/// </summary>
/// <param name="target"></param>
private void DispatchWeaponDamage(Transform target)
{
if (target == null)
{
return;
}
float time = Vector3.Distance(base.transform.position, target.position) / this.CurrentWeapon.MaxAimDistance;
float num = this.CurrentWeapon.FireDamageDistanceFactor.Evaluate(time);
float hitDamage = this.CurrentWeapon.PrevFireDamage * num;
PlayerWeaponDamageInfo playerWeaponDamageInfo = new PlayerWeaponDamageInfo(target, hitDamage);
IPlayerWeaponTarget asWeaponTarget = playerWeaponDamageInfo.AsWeaponTarget;
if (asWeaponTarget != null)
{
asWeaponTarget.ReceiveDamage(playerWeaponDamageInfo);
}
GameMessenger.Broadcast<PlayerWeaponDamageInfo>("PlayerWeaponDamageDispatched", playerWeaponDamageInfo);
}
sing System;
using UnityEngine;
public interface IPlayerWeaponTarget
{/// <summary>
/// 受到伤害
/// </summary>
/// <param name="damage"></param>
void ReceiveDamage(PlayerWeaponDamageInfo damage);
/// <summary>
/// 获取目标
/// </summary>
/// <returns></returns>
Transform GetPlayerAimTarget();
bool CamAimTo();
}
using System;
using UnityEngine;
//玩家武器目标扩展
public static class PlayerWeaponTargetExtensions
{
public static bool IsZombie(this IPlayerWeaponTarget target)
{
return target is ZombieController;
}
public static ZombieController AsZombie(this IPlayerWeaponTarget target)
{
return target as ZombieController;
}
// 计算玩家到目标的角度
public static float CalculateAngleFromPlayerToTarget(this IPlayerWeaponTarget target, bool fixBigZombieAngleOffset = true)
{
ZombieController zombieController = target.AsZombie();
float num = 1f;
if (zombieController != null && fixBigZombieAngleOffset && zombieController.IsBig)
{
num = zombieController.transform.localScale.x;
zombieController.transform.localScale = new Vector3(zombieController.DefaultScale, zombieController.DefaultScale, zombieController.DefaultScale);
}
Vector3 to = target.GetPlayerAimTarget().position - PlayerController.Instance.transform.position;
if (zombieController != null && fixBigZombieAngleOffset && zombieController.IsBig)
{
zombieController.transform.localScale = new Vector3(num, num, num);
}
to.Normalize();
return Mathf.Abs(Vector3.Angle(PlayerController.Instance.transform.forward, to));
}
/// <summary>
/// 在球员前面
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
public static bool IsAheadFromPlayer(this IPlayerWeaponTarget target)
{
//position.z 方法待考证
return target.GetPlayerAimTarget().transform.position.z >= PlayerController.Instance.transform.position.z;
}
/// <summary>
/// 获取目标屏幕空间位置
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
public static Vector2 GetAimTargetScreenSpacePosition(this IPlayerWeaponTarget target)
{
return PlayerMainCameraSystem.Instance.MainCamera.WorldToScreenPoint(target.GetPlayerAimTarget().position);
}
/// <summary>
/// 与玩家保持大致距离
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
public static float GetApproximateDistanceFromPlayer(this IPlayerWeaponTarget target)
{
return Mathf.Abs
(PlayerController.Instance.transform.position.z
- target.GetPlayerAimTarget().position.z);
}
}