p=65 CloneAttack (克隆攻击) ;类恶魔城Demo学习
思路: 克隆的动画与本体的动画一样,所以也带有动画事件evens(AnimationTrigger与AttackCheck);克隆检查到前方有敌人时可以攻击(并且调用怪物damage)。检查操作之前写过直接复制,既用Collider2d记录前面一个圆形区域。然后foreach找里面有没有enemy。
Clone_Skill_Controller.cs
public void AttackCheck()
{
//一个圆的碰撞体 (数组)
Collider2D[] colliders = Physics2D.OverlapCircleAll(attackCheck.position, attackCheckRadius);
foreach (var hit in colliders)
{
if (hit.GetComponent<Enemy>() != null)
{
hit.GetComponent<Enemy>().Damage();
}
}
}
public void AnimationTrigger()
{
cloneTime = -0.1f; //攻击完就开始渐变消失
}
private void Update()
{
cloneTime -= Time.deltaTime;
//sr.color = new Color(1, 1, 1, sr.color.a * 0.5f);
if (cloneTime < 0)
{
sr.color = new Color(1, 1, 1, sr.color.a - (colorLoosingSpeed * Time.deltaTime));
if (sr.color.a <= 0) //新加
Destroy(gameObject); //破坏掉
}
}
功能:克隆默认是看右的,我们要想克隆体对着最近怪物方向
思路:在自身半径能寻找敌人,遍历该半径有没有敌人,记录下每次敌人与自身的距离,最后找到最小值(记录的变量类似遍历数组找最小值)。最后判断敌人的x是否小于克隆的x(既是否左边出怪),如果是就克隆翻转。
注:Vector2.Distance(坐标1, 坐标2) : 两点之间的距离
public void FacingClosetEnemy()
{
float distanceToEnemy; //这次与敌人的距离
float closetEnemyDistance = Mathf.Infinity; //目前为止最近的距离
//自身的25半径
Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position , 25);
foreach (var hit in colliders)
{
if (hit.GetComponent<Enemy>() != null)
{
distanceToEnemy = Vector2.Distance(transform.position, hit.transform.position);
if (distanceToEnemy < closetEnemyDistance) //找到最近的敌人
{
closetEnemyDistance= distanceToEnemy;
closetEnemy = hit.transform;
}
}
}
if (closetEnemy != null)
{
if (closetEnemy.position.x < transform.position.x)
{
transform.Rotate(0, 180, 0);
}
}
}
整个该cs的代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//此脚本在prefab中plyaer_clone引用
public class Clone_Skill_Controller : MonoBehaviour
{
private SpriteRenderer sr;
private Animator anim;
private float colorLoosingSpeed; //CloneSkill传来
private float cloneTime;
[SerializeField] private Transform attackCheck;
[SerializeField] private float attackCheckRadius = 0.8f;
[SerializeField] private Transform closetEnemy; //附近的敌人
private float faceDir; //朝向敌人的方向
private void Awake()
{
sr = GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>();
}
private void Update()
{
cloneTime -= Time.deltaTime;
//sr.color = new Color(1, 1, 1, sr.color.a * 0.5f);
if (cloneTime < 0)
{
sr.color = new Color(1, 1, 1, sr.color.a - (colorLoosingSpeed * Time.deltaTime));
if (sr.color.a <= 0)
Destroy(gameObject);
}
}
//这里的 transform是克隆体的,因为这个脚本放在克隆组件里
//传入的值赋予克隆体
public void SetupClone(Transform _newTransform,float cloneDuration, float _colorLoosingSpeed, bool _canAttack)
{
Debug.Log("已经调用SetupClone");
if (_canAttack)
{
anim.SetInteger("AttackNumber", Random.Range(1, 4));
}
//设置clone放置位置,持续时间,消失速度
transform.position = _newTransform.position;
cloneTime = cloneDuration;
colorLoosingSpeed = _colorLoosingSpeed;
FacingClosetEnemy(); //对着正确的方向
}
public void AnimationTrigger()
{
cloneTime = -0.1f;
}
public void AttackCheck()
{
//一个圆的碰撞体 (数组)
Collider2D[] colliders = Physics2D.OverlapCircleAll(attackCheck.position, attackCheckRadius);
foreach (var hit in colliders)
{
if (hit.GetComponent<Enemy>() != null)
{
hit.GetComponent<Enemy>().Damage();
}
}
}
public void FacingClosetEnemy()
{
float distanceToEnemy; //这次与敌人的距离
float closetEnemyDistance = Mathf.Infinity; //目前为止最近的距离
//自身的25半径
Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position , 25);
foreach (var hit in colliders)
{
if (hit.GetComponent<Enemy>() != null)
{
distanceToEnemy = Vector2.Distance(transform.position, hit.transform.position);
if (distanceToEnemy < closetEnemyDistance) //找到最近的敌人
{
closetEnemyDistance= distanceToEnemy;
closetEnemy = hit.transform;
}
}
}
if (closetEnemy != null)
{
if (closetEnemy.position.x < transform.position.x)
{
transform.Rotate(0, 180, 0);
}
}
}
}
最后
日记:昨天写完今天下午开始写突然发现报错了(找不到SkillManager对象),排查后发现可能是调了代码的位置,player的skill = SkillManager.instance;放在awake不行,要在update才行
protected override void Start()
{
//Debug.Log("开始");
base.Start();
stateMachine.Initialize(idleState);
skill = SkillManager.instance; //静态方法,这样就算创对象了 BUG修复!!! 放awake会出错,Object未加载
}