SAIMA/Assets//脚本/Person.cs
Roman b66d86645e 任务:开发人马分离系统
分析:
1.其是与马并列的存在
2.具有状态:Normal:骑在马背,Shoot:从发射到着地到平台,Walk:在平台行走,landing:降落,Recover:若成功降落至马背,从刚判定成功到恢复到Normal态的中间态,为Recover态,Dead:判定为失败的瞬间以后都为Dead态。
3.效果要求:到达障碍物前某一位置后,人自动弹射,降落至平台,然后开始匀速移动,脱离平台后降落,之后持续判定是进入Recover还是Dead态。进入Recover态后,修正其偏移,使其回到默认的位置,Dead后,触发GameOver事件。

子任务:使人紧紧跟随马
1.当人处于Normal态,每帧同步人的位置和旋转到马背某处。
效果正常。
DONE

子任务:设计障碍物
1.仅跑道有碰撞体。
2.在障碍物主体之前有触发器,保证用户通过时能检测到,当检测到人进入触发器时,触发人的函数,Shoot()。这个触发仅有一次。
3.当检测到人着陆到平台上,触发人的函数Land()。
4.当检测到人离开平台,触发人的函数FallOff()
DONE

子任务:完成人的Shoot、Land、Falloff函数
Shoot:
1.给予刚体一个固定的朝向右上角的速度,使其刚好能抛到平台上。
2.从Shoot到Walk,大约有1~2秒时间,不能让人脸着地前进吧。所以,需要在1秒内修正人的旋转,修正完后锁定刚体Z旋转。
Good Job!效果不错
DONE

Land:
1.此时人脚着地处于平台上,让人按照固定的速度一直朝着右边前进即可
比较简单
DONE

FallOff:
由于胶囊碰撞体的特殊性,下落时会触发多次FallOff,这是不行的。同时,人在边缘直接坠落非常难看,所以这里加上一段小跳跃。
1.当触发FallOff,给刚体一个右上的速度,模拟跳跃
Good Job,效果很不错
DONE

子任务:完成马接住人的判定和控制系统
1.在马背安置触发器,当检测到玩家进入,触发人的Recover函数
2.完成人的Recover函数,使人在短时间内回到指定的位置和旋转,恢复的最后把人的状态恢复到Normal
DONE

子任务:开发,人直接掉落到地面的死亡逻辑
1.直接掉落到地面后,触发GameOver

子任务:测试
1.发现人Recover功能的问题,Recover时的目标点是固定的,但是恢复的过程中马会动,所以这种办法从根本上就有问题。再多写一个动态的追踪比较麻烦,姑且让人恢复得快一点,这样就看不出来什么破绽。
已解决
2.人有时发射不到人马分离的平台上,应该是发射速度太小导致的,已调大。
3.我认为现在创烂障碍物的速度门槛太低了,已适当加快
4.人马分离障碍会突然出现而不是从屏幕右侧进入出现,这是人马分离障碍体积过大导致的。目前只能适当右移障碍物生成点解决。
5.发现Bug,本来可创烂障碍物的爆破力度会随着马的速度而改变,但现在经常响应不到。
已修复。

暂未发现更多问题。

至此,人马分离障碍物的逻辑基本完成

*修复Bug
1.原先马在触发器也会被阻挡,这是因为马脚供力的算法的错误导致的,要从根本解决需要修改复杂的算法,所以这里使用Trick,将触发器的物理层转移到忽略射线检测层,解决了这个问题。
DONE
2.发现Bug,本来可创烂障碍物的爆破力度会随着马的速度而改变,但现在经常响应不到。原来监听的是马的速度,由于整个数学模型的特殊性,马本体的速度变化极其诡异,所以易导致监听错误。应采用新的监听方式,不再监听马本体速度,而是监听用户过去若干时间内的输入变化,由此来决定爆破力度。
不是!我的代码没问题,是这个插件的作者的代码的问题,非常啥卵。已通过修改插件作者源码解决问题。
DONE
2022-08-19 14:23:35 +08:00

160 lines
5.0 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 DG.Tweening;
using Sirenix.OdinInspector;
/// <summary>
/// 马背上人的控制类
/// </summary>
public class Person : MonoBehaviour
{
public enum PersonState{
Normal,//骑在马背
Shoot,//从发射到着地平台
Walk,//在平台行走
FallingOff,//下落,从脱离平台到判定有结果前
Recover,//判定成功到恢复到Normal的过程态
Dead//判定失败后均为此态
}
/// <summary>
/// 人此时的状态
/// </summary>
[Header("信息显示")]
[Title("人此时的状态")]
[EnumPaging()]
public PersonState state;
/// <summary>
/// 人在人马分离障碍的平台上时的行走速度
/// </summary>
[FoldoutGroup("主要参数",true)]
[Title("人在人马分离障碍的平台上时的行走速率")]
public float walkSpeed = 1f;
/// <summary>
/// 人在人马分离障碍前,被抛出的速度
/// </summary>
[FoldoutGroup("附加参数",false)]
[Title("人在人马分离障碍前,被抛出的速度")]
public Vector2 throwingSpeed;
[FoldoutGroup("附加参数",false)]
[Title("人在离开平台时起跳的速度")]
public Vector2 jumpSpeed;
[FoldoutGroup("附加参数")][Title("人死后的飞出速度")]
public Vector2 deadFlyVeloctiy;
[FoldoutGroup("附加参数")][Title("人死后的飞出的旋转的角速度")]
public float deadFlyRotateSpeed;
/// <summary>
/// 默认状态下的追踪点
/// </summary>
private Transform defaultTrackingPoint;
private Rigidbody2D m_rigidbody2D;
void Start(){
//Init
//Init
//Find
defaultTrackingPoint = GameObject.Find("人的默认位置(不可改名)").transform;
m_rigidbody2D = GetComponent<Rigidbody2D>();
//Find
}
void Update(){
//默认状态下的Update
if(state == PersonState.Normal){
//同步人和马的位置和旋转
transform.position = defaultTrackingPoint.position;
transform.rotation = defaultTrackingPoint.rotation;
}
//行走状态下的Update
else if(state == PersonState.Walk){
//让人向右移动
transform.position += (Vector3.right * walkSpeed * Time.deltaTime);
}
}
/// <summary>
/// 人发射的瞬间触发,由人马分离障碍物触发
/// </summary>
public void Shoot(){
Debug.Log("人发射");
state = PersonState.Shoot;
//给与刚体一个右上角的速度,使其刚好能抛到平台上
m_rigidbody2D.velocity = throwingSpeed;
//1秒内修正人的旋转
transform.DORotate(new Vector3(0,0,0),1).OnComplete(
//旋转修正结束后锁定刚体Z轴旋转
() => m_rigidbody2D.constraints = RigidbodyConstraints2D.FreezeRotation
);
}
/// <summary>
/// 人接触到平台的瞬间触发,由人马分离障碍物触发
/// </summary>
public void Walk(){
Debug.Log("人行走");
state = PersonState.Walk;
}
/// <summary>
/// 人离开平台的瞬间触发,由人马分离障碍物触发
/// </summary>
public void FallingOff(){
Debug.Log("人降落");
state = PersonState.FallingOff;
//给刚体一个右上的速度,模拟一下起跳
m_rigidbody2D.velocity = jumpSpeed;
}
public void Recover(){
Debug.Log("人成功降落到马背");
state = PersonState.Recover;
//1秒内修正人的位置和旋转与defaultTrackingPoint同步
//后发现,由于追踪的动画终点是定好了的,但是马在这一秒还是会运动,会导致问题,所以这里把时间改短
transform.DOMove(defaultTrackingPoint.position,0.2f);
transform.DORotate(defaultTrackingPoint.rotation.eulerAngles,0.2f).OnComplete(
() => state = PersonState.Normal
);
}
/// <summary>
/// 由GameController触发用于控制人死后的动作
/// </summary>
public void Death(GameController.Death deathInfo){
state = PersonState.Dead;
//让人和马一样,旋转着飞出去,同时关闭自身的碰撞体
GetComponent<CapsuleCollider2D>().enabled = false;
Rigidbody2D rigidbody2D = GetComponent<Rigidbody2D>();
rigidbody2D.velocity = deadFlyVeloctiy;
rigidbody2D.angularVelocity = deadFlyRotateSpeed;
}
private void OnCollisionEnter2D(Collision2D other) {
//如果创到地面,且是在降落状态,则判定为游戏失败
if(other.gameObject.tag == "Ground" && state == PersonState.FallingOff){
GameController.Death death = new GameController.Death();
death.deadReason = GameController.Death.DeadReason.PersonFall;
GameController.Instance.GameOver(death);
Debug.Log("人掉落到地面");
}
}
}