c1_unity/Assets/Scripts/Component/Battle/BattleControlMonster.cs
2023-04-03 11:04:31 +08:00

582 lines
19 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
namespace BF
{
public class BattleControlMonster : BattleControlUnit
{
private CharacterSpineHelper spineHelper;
private Rigidbody unitRigidbody;
private Transform mainBody;
private bool isMoving = false;
private float checkTowardTime = 0.1f;
private float checkAITargetPositionTime = 0.1f;
private int horizontalTypeAI = 0;
private float offsetXAI = 0.0f;
private float offsetZAI = 0.0f;
private Sequence airborneSeq;
private bool isHitBack = true;
private float hitBackTime = 0.0f;
private float hitBackSpeed = 0.0f;
void Awake()
{
InitRigidbody();
}
private void InitRigidbody()
{
if (!gameObject.TryGetComponent<Rigidbody>(out unitRigidbody))
{
unitRigidbody = gameObject.AddComponent<Rigidbody>();
}
unitRigidbody.angularDrag = 0;
unitRigidbody.useGravity = false;
unitRigidbody.isKinematic = true;
unitRigidbody.constraints = BattleConst.RIGIDBODY_CONSTRAINTS;
bodyCollider = gameObject.AddComponent<SphereCollider>();
bodyCollider.isTrigger = true;
}
public void InitMonster(int side, CharacterSpineHelper helper, Transform body)
{
Side = side;
BattleMgr = BF.BFMain.Instance.BattleMgr;
spineHelper = helper;
mainBody = body;
if (ReferenceEquals(mainBody, null))
{
mainBody = transform.GetChild(0);
}
Direction = 1;
isMoving = false;
IsDead = false;
IsInGroundState = false;
Target = null;
IsDisappear = false;
BattleMgr.AddToDefUnitsList(this);
gameObject.layer = BattleConst.LAYER_MONSTER;
}
public override void InitHpBar()
{
if (isHaveHpBar)
{
return;
}
hpBar = BattleMgr.PoolHelper.GetHpBar(Side);
hpBar.transform.localScale = Vector3.one;
hpBar.RefreshHpBar(1.0f);
BattleMgr.UpdateUIPosition(transform.position, HpBarAddY, hpBar.transform as RectTransform);
isHaveHpBar = true;
}
public override void RefreshHpBar(float percent)
{
if (!isHaveHpBar)
{
return;
}
hpBar.RefreshHpBar(percent);
}
public void InitPosition(float x, float y, float z)
{
transform.position = new Vector3(x, y, z);
}
public override void EnterDisappear()
{
gameObject.layer = BattleConst.LAYER_DEFAULT;
BattleMgr.RemoveFromDefUnitsList(this);
if (isHaveHpBar)
{
hpBar.transform.localScale = Vector3.zero;
}
if (IsHaveShadow)
{
shadow.transform.localScale = Vector3.zero;
}
}
public override void ExitDisappear()
{
gameObject.layer = BattleConst.LAYER_MONSTER;
BattleMgr.AddToDefUnitsList(this);
if (isHaveHpBar)
{
hpBar.transform.localScale = Vector3.one;
}
if (IsHaveShadow)
{
shadow.transform.localScale = Vector3.one*BodyRadius*2.0f;
}
}
public void SetTarget(BattleControlUnit target)
{
Target = target;
}
public bool GetIsNormalMonster()
{
return true;
}
public bool GetIsBOSS()
{
return false;
}
public void StopMove()
{
isMoving = false;
}
public void StartMove()
{
isMoving = true;
}
// 秒杀
public void InstantKill()
{
OnDead();
}
public override void PlayAirborne()
{
if (ReferenceEquals(airborneSeq, null))
{
airborneSeq = BattleHelper.CreateSequence();
var time = BattleConfigure.TimeHitFly;
var tween1 = mainBody.DOLocalMoveY(BattleConfigure.HeightHitFly, time*3.0f/5.0f).SetEase(Ease.OutQuart);
tween1.intId = BattleConst.DOTWEEN_ID_BATTLE;
var tween2 = mainBody.DOLocalMoveY(0.0f, time*2.0f/5.0f);
tween2.intId = BattleConst.DOTWEEN_ID_BATTLE;
airborneSeq.Append(tween1);
airborneSeq.Append(tween2);
airborneSeq.SetAutoKill(false);
}
else
{
airborneSeq.Restart();
}
isHitBack = true;
hitBackTime = BattleConfigure.TimeHitFly;
hitBackSpeed = BattleConfigure.DistanceHitFly / hitBackTime;
}
public override void StopAirborne()
{
if (!ReferenceEquals(airborneSeq, null))
{
airborneSeq.Pause();
}
mainBody.localPosition = Vector3.zero;
}
public override void MoveWithSkillAI(int target, int horizontal, float x, float z, int refresh, int across, float speed, int endType, float endValue, int collisionType)
{
StartMove();
targetTypeAI = target;
horizontalTypeAI = horizontal;
offsetXAI = x;
offsetZAI = z;
keepUpdateTargetPositionAI = refresh == 1;
isCanAcrossTarget = across == 1;
moveSpeedAI = speed;
isTeleport = moveSpeedAI < 0.000001f;
endTypeAI = endType;
if (endTypeAI == 1)
{
endValueAI = endValue*endValue;
}
else
{
endValueAI = endValue;
}
collisionTypeAI = collisionType;
FindTargetPosition();
}
private void FindTargetPosition()
{
if (targetTypeAI == 1) // 自身
{
FindTargetPositionAISelf();
CheckTargetPositionAIOutWall();
}
else if(targetTypeAI == 2) // 目标
{
FindTargetPositionAITarget();
CheckTargetPositionAIOutWall();
}
else if(targetTypeAI == 3) // 场地中央
{
FindTargetPositionAIMiddle();
CheckTargetPositionAIOutWall();
}
else
{
StopMove();
}
}
private void FindTargetPositionAITarget()
{
if (horizontalTypeAI == 1)
{
if (Target.transform.position.x < transform.position.x) // 目标在自己的左边
{
targetPositionAI = Target.transform.position + new Vector3(-offsetXAI, 0.0f, offsetZAI);
}
else
{
targetPositionAI = Target.transform.position + new Vector3(offsetXAI, 0.0f, offsetZAI);
}
}
else if(horizontalTypeAI == 2)
{
var deltaX = transform.position.x - Target.transform.position.x;
var deltaZ = transform.position.z - Target.transform.position.z;
var radian = Mathf.Atan2(deltaZ, deltaX);
var x = -offsetXAI*Mathf.Cos(radian);
var z = -offsetXAI*Mathf.Sin(radian);
targetPositionAI = new Vector3(Target.transform.position.x + x, 0.0f, Target.transform.position.z + z);
}
}
private void FindTargetPositionAISelf()
{
if (Direction == 1)
{
targetPositionAI = transform.position + new Vector3(offsetXAI, 0.0f, offsetZAI);
}
else
{
targetPositionAI = transform.position + new Vector3(-offsetXAI, 0.0f, offsetZAI);
}
}
private void FindTargetPositionAIMiddle()
{
if (horizontalTypeAI == 1)
{
if (BattleConfigure.SceneMidX < transform.position.x) // 自己在场景右边
{
targetPositionAI = new Vector3(-offsetXAI + BattleConfigure.SceneMidX, 0.0f, offsetZAI + BattleConfigure.SceneMidZ);
}
else
{
targetPositionAI = transform.position + new Vector3(offsetXAI + BattleConfigure.SceneMidX, 0.0f, offsetZAI + BattleConfigure.SceneMidZ);
}
}
else if(horizontalTypeAI == 2)
{
var deltaX = transform.position.x - BattleConfigure.SceneMidX;
var deltaZ = transform.position.z - BattleConfigure.SceneMidZ;
var radian = Mathf.Atan2(deltaZ, deltaX);
var x = -offsetXAI*Mathf.Cos(radian);
var z = -offsetXAI*Mathf.Sin(radian);
targetPositionAI = new Vector3(Target.transform.position.x + x, 0.0f, Target.transform.position.z + z);
}
}
private void CheckTargetPositionAIOutWall()
{
if (targetPositionAI.x < BattleConfigure.SceneMinX) // 撞左边墙了
{
targetPositionAI.x = BattleConfigure.SceneMinX;
}
else if (targetPositionAI.x > BattleConfigure.SceneMaxX) // 撞右边墙了
{
targetPositionAI.x = BattleConfigure.SceneMaxX;
}
if (targetPositionAI.z < BattleConfigure.SceneMinZ) // 撞左边墙了
{
targetPositionAI.z = BattleConfigure.SceneMinZ;
}
else if (targetPositionAI.z > BattleConfigure.SceneMaxZ) // 撞右边墙了
{
targetPositionAI.z = BattleConfigure.SceneMaxZ;
}
}
void Update()
{
var deltaTime = Time.deltaTime*BattleConfigure.TimeScale;
if (!isMoving)
{
if (isHitBack)
{
UpdateHitBackMove(deltaTime);
}
CheckToward(deltaTime);
return;
}
UpdateAIMoveing(deltaTime);
}
void LateUpdate()
{
// TODO 后续可以优化成怪物移动或者相机移动的时候更新
if (isHaveHpBar)
{
BattleMgr.UpdateUIPosition(transform.position, HpBarAddY, hpBar.transform as RectTransform);
}
}
private void CheckToward(float deltaTime)
{
if (IsDead)
{
return;
}
checkTowardTime -= deltaTime;
if (checkTowardTime < 0.0f)
{
checkTowardTime = BattleConfigure.CheckMonsterTowardInterval;
TowardToTarget();
}
}
public override void TowardToTarget()
{
if (Target.transform.position.x <= transform.position.x)
{
if (Direction != -1)
{
Direction = -1;
var bodyTransform = spineHelper.GetSpineObject().transform.parent;
bodyTransform.localScale = new Vector3(BattleConfigure.MonsterScaleFactorXZ*Direction, bodyTransform.localScale.y, bodyTransform.localScale.z);
}
}
else
{
if (Direction != 1)
{
Direction = 1;
var bodyTransform = spineHelper.GetSpineObject().transform.parent;
bodyTransform.localScale = new Vector3(BattleConfigure.MonsterScaleFactorXZ*Direction, bodyTransform.localScale.y, bodyTransform.localScale.z);
}
}
}
public override void ForceTowardToTarget()
{
if (Target.transform.position.x <= transform.position.x)
{
Direction = -1;
var bodyTransform = spineHelper.GetSpineObject().transform.parent;
bodyTransform.localScale = new Vector3(BattleConfigure.MonsterScaleFactorXZ*Direction, bodyTransform.localScale.y, bodyTransform.localScale.z);
}
else
{
Direction = 1;
var bodyTransform = spineHelper.GetSpineObject().transform.parent;
bodyTransform.localScale = new Vector3(BattleConfigure.MonsterScaleFactorXZ*Direction, bodyTransform.localScale.y, bodyTransform.localScale.z);
}
}
private void UpdateAIMoveing(float deltaTime)
{
if (endTypeAI == 1) // 按距离结束
{
if ((transform.position - targetPositionAI).sqrMagnitude < endValueAI)
{
FinishAIMove();
return;
}
}
else if(endTypeAI == 2) // 按时间结束
{
endValueAI -= deltaTime;
if (endValueAI < 0.0f)
{
FinishAIMove();
return;
}
}
else
{
if ((transform.position - targetPositionAI).sqrMagnitude < 0.0001)
{
return;
}
}
MoveToTarget(deltaTime);
if (keepUpdateTargetPositionAI)
{
checkAITargetPositionTime -= deltaTime;
if (checkAITargetPositionTime < 0.0f)
{
checkAITargetPositionTime = BattleConfigure.CheckAITargetPositionInterval;
FindTargetPosition();
}
}
}
private void MoveToTarget(float deltaTime)
{
Vector3 moveToPosition;
if (isTeleport)
{
if (isHitBack)
{
hitBackTime -= deltaTime;
if (hitBackTime < 0.0f)
{
isHitBack = false;
}
}
moveToPosition = targetPositionAI;
}
else
{
if (isHitBack)
{
hitBackTime -= deltaTime;
if (hitBackTime < 0.0f)
{
isHitBack = false;
}
moveToPosition = Vector3.MoveTowards(transform.position, transform.position + new Vector3(BattleConst.UNIT_MOVE_DISTANCE_OPPOSITE*Direction, 0.0f, 0.0f), hitBackSpeed * deltaTime);
}
else
{
moveToPosition = Vector3.MoveTowards(transform.position, targetPositionAI, moveSpeedAI * deltaTime);
}
}
if (!isCanAcrossTarget) // 不能穿过目标
{
if (Target.transform.position.x <= transform.position.x) // 在目标左边
{
var limitX = Target.transform.position.x + Target.BodyRadius + BodyRadius;
if (moveToPosition.x < limitX)
{
moveToPosition.x = limitX;
}
}
else
{
var limitX = Target.transform.position.x - Target.BodyRadius - BodyRadius;
if (moveToPosition.x > limitX)
{
moveToPosition.x = limitX;
}
}
}
if (moveToPosition.x < BattleConfigure.SceneMinX) // 撞左边墙了
{
moveToPosition.x = BattleConfigure.SceneMinX;
}
else if (moveToPosition.x > BattleConfigure.SceneMaxX) // 撞右边墙了
{
moveToPosition.x = BattleConfigure.SceneMaxX;
}
if (moveToPosition.z < BattleConfigure.SceneMinZ) // 撞左边墙了
{
moveToPosition.z = BattleConfigure.SceneMinZ;
}
else if (moveToPosition.z > BattleConfigure.SceneMaxZ) // 撞右边墙了
{
moveToPosition.z = BattleConfigure.SceneMaxZ;
}
transform.position = moveToPosition;
}
private void UpdateHitBackMove(float deltaTime)
{
hitBackTime -= deltaTime;
if (hitBackTime < 0.0f)
{
isHitBack = false;
}
var moveToPosition = Vector3.MoveTowards(transform.position, transform.position + new Vector3(BattleConst.UNIT_MOVE_DISTANCE_OPPOSITE*Direction, 0.0f, 0.0f), hitBackSpeed * deltaTime);
if (Target.transform.position.x <= transform.position.x) // 在目标左边
{
var limitX = Target.transform.position.x + Target.BodyRadius + BodyRadius;
if (moveToPosition.x < limitX)
{
moveToPosition.x = limitX;
}
}
else
{
var limitX = Target.transform.position.x - Target.BodyRadius - BodyRadius;
if (moveToPosition.x > limitX)
{
moveToPosition.x = limitX;
}
}
if (moveToPosition.x < BattleConfigure.SceneMinX) // 撞左边墙了
{
moveToPosition.x = BattleConfigure.SceneMinX;
}
else if (moveToPosition.x > BattleConfigure.SceneMaxX) // 撞右边墙了
{
moveToPosition.x = BattleConfigure.SceneMaxX;
}
if (moveToPosition.z < BattleConfigure.SceneMinZ) // 撞左边墙了
{
moveToPosition.z = BattleConfigure.SceneMinZ;
}
else if (moveToPosition.z > BattleConfigure.SceneMaxZ) // 撞右边墙了
{
moveToPosition.z = BattleConfigure.SceneMaxZ;
}
transform.position = moveToPosition;
}
public override void BeHitBack()
{
if (isHitBack)
{
return;
}
isHitBack = true;
hitBackTime = BattleConfigure.HitBackTime;
hitBackSpeed = BattleConfigure.DistanceHitBack / hitBackTime;
}
private void FinishAIMove()
{
StopMove();
luaOnFinishAIMoveFunc?.Invoke();
}
public override void OnDead()
{
IsDead = true;
IsInGroundState = false;
BattleMgr.RemoveFromDefUnitsList(this);
}
public override void Clear()
{
luaOnHitTargetFunc = null;
luaOnFinishAIMoveFunc = null;
if (isHaveHpBar)
{
BattleMgr.PoolHelper.PutBackHpBar(hpBar, Side);
hpBar = null;
isHaveHpBar = false;
}
}
private void OnDestroy()
{
luaOnHitTargetFunc = null;
luaOnFinishAIMoveFunc = null;
if (!ReferenceEquals(airborneSeq, null))
{
airborneSeq.Kill();
}
}
}
}