religion/Assets/Scripts/AiYuPin.cs
Roman 5bff5da713 任务:搭建基本的系统
1.修改爱欲品类,解决多个附身的问题
(1.已有变量标记玩家是否正被抓着
(*.当玩家被爱欲品抓住,让玩家记住这个爱欲品,用来后面被多个缠上时清空它的挣脱次数
(2.当爱欲品创到玩家,检查目前是否已经被附身,若是,使用父类的touched函数,也就是普通小怪的,用来创飞玩家,同时,清空当前附身着的爱欲品的挣脱次数
(3.修改爱欲品附身时的跟踪方式,原先为一次定位后不再更改,但如果遇到多只爱欲品的情况,则可能被击飞,此时附身中的爱欲品不会跟踪。修改至攻击中每帧重新定位。

2.编写地藏的敲钟攻击逻辑
(1.钟上浮Tween动画
(2.Tween动画结束事件,开启开关,同时StartContinue,等待一定时间后关闭开关,用来触发攻击结束事件
(3.开关打开时,每帧向玩家发射射线,若能击中玩家,受伤方式等待讨论确认。若不能,则无事可做。

3.整理脚本结构,编写注释、摘要和分层

至此,地藏的敲钟攻击逻辑基本完成
2021-12-10 00:23:50 +08:00

201 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Sirenix.OdinInspector;
/// <summary>
/// 爱欲品类,继承自三关都有的那个小怪类
/// </summary>
public class AiYuPin : NormalEnemy
{
// _____ _ _ _
// | __ \ | | | (_)
// | |__) | _| |__ | |_ ___
// | ___/ | | | '_ \| | |/ __|
// | | | |_| | |_) | | | (__
// |_| \__,_|_.__/|_|_|\___|
/// <summary>
/// 爱欲品抓住玩家后贴在玩家身上时的位置偏移量
/// </summary>
[FoldoutGroup("爱欲品")][Header("爬到玩家身上的时候的位置偏移量")]
public Vector3 catchOffset;
/// <summary>
/// 玩家挣脱爱欲品需要多少次方向转换操作
/// </summary>
[Header("玩家挣脱爱欲品需要多少次方向转换操作")][FoldoutGroup("爱欲品")]
public int breakFreeCount;
/// <summary>
/// 玩家挣脱爱欲品还需要多少次方向转换操作
/// </summary>
[Header("玩家挣脱爱欲品还需要多少次方向转换操作")][FoldoutGroup("爱欲品")][ReadOnly]
public int breakFreeCountLeft;
// _____ _ _
// | __ \ (_) | |
// | |__) | __ ___ ____ _| |_ ___
// | ___/ '__| \ \ / / _` | __/ _ \
// | | | | | |\ V / (_| | || __/
// |_| |_| |_| \_/ \__,_|\__\___|
/// <summary>
/// 爱欲品发动Seek后追击的目标
/// </summary>
//虽说是目标,但爱欲品只会抓玩家吧。直接初始化成玩家了
protected Transform target;
/// <summary>
/// 记录当前自己是否抓着玩家
/// </summary>
private bool isCatching = false;
// _____ _ _ ____ _
// / ____| | | | _ \ | |
// | | __ _| | | |_) | __ _ ___| | __
// | | / _` | | | _ < / _` |/ __| |/ /
// | |___| (_| | | | |_) | (_| | (__| <
// \_____\__,_|_|_|____/ \__,_|\___|_|\_\
void Update(){
//如果在Seek状态则Seek
if(state == State.seek) Seek(target);
if(isCatching){
//将自身位置和玩家位置同步但是需要一个附身offset二维向量
//因为玩家的图片不在游戏物体的中心
transform.position = target.position + catchOffset;
}
}
// _ _ _
// | \ | | | |
// | \| | ___ _ __ _ __ ___ __ _| |
// | . ` |/ _ \| '__| '_ ` _ \ / _` | |
// | |\ | (_) | | | | | | | | (_| | |
// |_| \_|\___/|_| |_| |_| |_|\__,_|_|
protected override void Init()
{
//初始化基础属性
base.Init();
//初始化爱欲品属性
breakFreeCountLeft = breakFreeCount;//初始化挣脱需要的操作次数
target = FindObjectOfType<MyPlayer>().transform;//初始化追踪目标为玩家
}
/// <summary>
/// 控制爱欲品追踪传入的Transform每帧调用一次
/// </summary>
/// <param name="target">要追踪的目标的transform组件</param>
protected virtual void Seek(Transform target){
Vector3 moveDir = (target.transform.position - transform.position).normalized;
//给刚体添加位移
m_rigidbody.position += (Vector2)moveDir * speed * Time.deltaTime * Vector2.right;
//将面部朝向与速度同步
transform.rotation = Quaternion.
Euler
(transform.rotation.x,
((target.position.x - transform.position.x > 0) ? 0:-180),
transform.rotation.z);
}
// ______ _
// | ____| | |
// | |____ _____ _ __ | |_
// | __\ \ / / _ \ '_ \| __|
// | |___\ V / __/ | | | |_
// |______\_/ \___|_| |_|\__|
/// <summary>
/// 当爱欲品发现玩家
/// </summary>
protected override void OnFindThePlayer(Transform target){
//如果没死
if(state == State.wander)
{
//标记自身状态
state = State.seek;
//赋予自身目标以玩家Transform
this.target = target;
//关闭巡逻动画
doTweenPath.DOPause();
}
}
/// <summary>
/// 当爱欲品抓住玩家
/// </summary>
protected override void OnTouchThePlayer(MyPlayer player)
{
//如果玩家没有被抓住,才执行抓住
if(!player.isCatching){
//通知玩家,你被爱欲品附身了
player.BeCatchedByAiYuPin(this);
//暂停Path动画
doTweenPath.DOPause();
//改变自身状态为ATK
state = State.atk;
//关闭自身碰撞体,因为要贴在玩家身上
GetComponent<BoxCollider2D>().enabled = false;
//将自身位置和玩家位置同步但是需要一个附身offset二维向量
//因为玩家的图片不在游戏物体的中心
transform.position = target.position + catchOffset;
//暂时清空重力系数
m_rigidbody.gravityScale = 0;
//清除一下刚体速度,不然怪物可能被创飞
m_rigidbody.velocity = Vector2.zero;
//清除角动量,不然可能会转起来
m_rigidbody.angularVelocity = 0;
//标记自身正抓着玩家
isCatching = true;
}
//如果玩家正被抓着则执行父类——普通小怪的Touch即击飞玩家
else{
base.OnTouchThePlayer(player);
//同时,清空当前附身着的爱欲品的挣脱次数
player.catingAiYuPin.breakFreeCountLeft = breakFreeCount;
}
}
/// <summary>
/// 当爱欲品被攻击了
/// </summary>
/// <param name="hitMethod">攻击方式</param>
/// <param name="hitDir">攻击来袭方向</param>
public override void OnBeHit(MyPlayer.AtkMethod hitMethod, int hitDir){
//爱欲品会额外触发发现玩家事件
target = FindObjectOfType<MyPlayer>().transform;//将目标指向玩家
OnFindThePlayer(target);//触发发现玩家事件
//执行被击飞、死亡检查等事宜
base.OnBeHit(hitMethod, hitDir);
//被打飞在着地前都不会挨打了
canBeHit = false;
}
//原先会触发自动返回记录起点,但是不能,所以重写空的重新着地事件
public override void OnRetouchedTheGround(){ canBeHit = true; }
/// <summary>
/// 完全挣脱的时候触发
/// </summary>
protected void OnBreakFreeCompletely(){
//恢复一下抓到玩家的时候消除的重力系数
m_rigidbody.gravityScale = 1;
//随机一个死亡面部朝向
deadDir = (Random.Range(-1f,1f) > 0) ? 1: -1;
//标记自身不再抓着玩家
isCatching = false;
//触发死亡事件
OnDead();
//给一个击飞
BeHitToFly((Random.Range(-1f,1f) > 0) ? 1: -1);
//通知玩家
FindObjectOfType<MyPlayer>().BreakFreeCompletely();
}
/// <summary>
/// 玩家尝试挣脱的时候触发这个
/// </summary>
public void OnBreakFree(){
if(--breakFreeCountLeft <= 0) OnBreakFreeCompletely();
}
}