由上一期简单的敌人跟随玩家,这次尝试的做了一个宠物跟随。相对来说并没有什么复杂的地方。
实现一个宠物跟随玩家,首先需要规定宠物活动的范围,要么等待要么自由的随机移动,当如果玩家离得它比较远时,就只需要让其追踪到玩家的位置即可,不过不能让宠物一回到范围就停下来,而是要让其距离玩家足够近处停下来,当如果玩家离宠物太远了宠物跟不上了,就让他传送到玩家附近的某个位置。本次的宠物系统大致就是实现的这样的功能。
让宠物追踪玩家前几期就有不少类似的做过的追踪功能,本次不做过多介绍。
但是要注意的是,不能让宠物直接到达玩家所在位置,因为这样会让宠物如果顶不动玩家,它就会一直顶着玩家从而无法切换运动状态,我们需要规定一个合适的距离(在玩家与宠物的碰撞区域外,如果你的宠物不需要和玩家碰撞另说),当它距离玩家到这个值的区间后,让它停下来切换为其它运动状态后即可。
传送宠物时,含有碰撞的宠物不适合直接传送到玩家的位置,因为这会导致玩家被挤开,所以需要让宠物在玩家附近选取一个点随机传送,我这里随机的位置是和宠物与玩家间靠近玩家位置的连线的随机位置,让然也可写成范围内随机点(也有这部分代码)。
接下来就是日常的上代码了:
所有属性
//一如既往的使用了大量的属性
public GameObject host;//需要跟随的主人,在编辑器界面设置
[Range(0, 20)]
public float Speed;//速度
[Range(0, 1000)]
public float Convey_Distance;//传送距离,超出这个距离就发生传送
[Range(0, 100)]
public float Max_Distance;//最大距离,超出这个距离就追随玩家
[Range(0, 10)]
public float Min_Distance;//最小距离,到达玩家位置前的某一点最小间隙
[Range(0, 10)]
public float Wait_time;//状态时间
[Range(0, 5)]
public float Time_Loop;//状态时间差异
private float Wait_time_set;//每一个状态时间过渡
private float Wait_time_current;//当前等待时间
private float Distance;//截止距离
private Rigidbody2D body;
private Vector2 direction;//移动方向
private int Move_method;//移动方式
private Vector2 Host_position;//传送用的位置
每帧执行的部分
当玩家和宠物距离过远时,就让它该改变移动状态,让它不再自由移动或者等待
void Update()
{
if (Get_Distance(host.transform.position) >= Convey_Distance)//距离太远发生传送
{
Host_Position();//给定一个传送位置
transform.position = Host_position;
}
else if (Get_Distance(host.transform.position) >= Max_Distance && Move_method != 11)//距离较远移动到玩家附近
{
//仅针对第一发生,之后便在到达玩家附近前将一直执行第三个判断
Distance = Random.Range(2f, Min_Distance);//给定一个和玩家贴近的距离
Move_method = 11;
Move_Host();
}
else if (Move_method == 11)//持续移动到玩家的位置
{
Move_Host();
}
else if (Move_method > 6)//随机移动
{
Move_Position(direction);
}
if (Wait_time_current >= Wait_time_set)//时间操作
{
Set_Direction();//设置新的随机移动方向
Wait_time_set = Random.Range(Wait_time - Time_Loop, Wait_time + Time_Loop);//设置新的行为持续时间
Wait_time_current = 0;
Move_method = Random.Range(0, 10);//设置新的行为状态
}
Wait_time_current += Time.deltaTime;
}
设置一个玩家和宠物连线上的距离位置,给定传送位置
思路是先建立一个连线向量rot,将其标准化,它的x值和y值和最大值与最小值相乘,就等得到在最大距离和最小距离之间的连线,在加上玩家本身的位置,就是玩家和宠物连线上,靠近玩家一侧的位置。
void Host_Position()
{
Vector2 rot = (transform.position - host.transform.position).normalized;
rot.x = Random.Range(Min_Distance * rot.x, Max_Distance * rot.x);
rot.y = Random.Range(Min_Distance * rot.y, Max_Distance * rot.y);
rot.x += host.transform.position.x;
rot.y += host.transform.position.y;
Host_position = rot;
}
移动向玩家
设置Move_method就是到达玩家附近,改变它的运动状态为等待或者自由移动
void Move_Host()//移动向玩家
{
if (Get_Distance(host.transform.position) <= Distance)
{
Move_method = Random.Range(0, 10);
Wait_time_current = 0;
}
Move_Position((host.transform.position - transform.position).normalized * 2);
}
这是另一种随机范围内位置的设置方式,但我没用过,但是对New_X和New_Y执行加减操作的意义是防止随机的位置离玩家太近(就是把你自己挤开)
//设想的第二个方法
//void Host_Position2()
//{
// float New_X = Random.Range(Min_Distance - Max_Distance , Max_Distance - Min_Distance);
// float New_Y = Random.Range(Min_Distance - Max_Distance , Max_Distance - Min_Distance);
// if(New_X < 0)
// {
// New_X -= Min_Distance;
// }
// else
// {
// New_X += Min_Distance;
// }
// if(New_Y < 0)
// {
// New_Y -= Min_Distance;
// }
// else
// {
// New_Y += Min_Distance;
// }
// Host_position = new Vector2(host.transform.position.x + New_X, host.transform.position.y + New_Y);
//}
看一看最终的实现效果是怎么样的吧