Unity开发一个FPS游戏之三

 这个系列的介绍已经完成,有兴趣的朋友可以查看以下链接

Unity开发一个FPS游戏_unity 模仿开发fps 游戏-优快云博客

Unity开发一个FPS游戏之二_unity 模仿开发fps 游戏-优快云博客

Unity开发一个FPS游戏之三-优快云博客

Unity开发一个FPS游戏之四_unity fps-优快云博客

Unity开发一个FPS游戏之五-优快云博客

所有的代码和资源已经上架Unity Asset Store, 链接是FPS basic package | Systems | Unity Asset Store

在前面的两篇博客中,我已实现了一个FPS游戏的大部分功能,包括了第一人称的主角运动控制,武器射击以及敌人的智能行为。这里我将继续完善这个游戏,包括以下几个方面:

  1. 增加一个真实的游戏场景,模拟一个废弃的工厂环境
  2. 完善NPC的智能行为,增加巡逻,警戒,躲避,战术编队等行为。
  3. 增加子弹与场景物体交互的效果。
  4. 游戏道具的拾取。
  5. 完善UI界面,增加场景的任务描述,任务完成或失败的判定展示。

以下是完成后的演示。

mission_critical

游戏场景设计

这是一个很大的课题,暂时不是我关注的重点,为此我先直接采用Unity商店的一个免费的资源,RPG/FPS Game Assets for PC/Mobile (Industrial Set v2.0) | 3D 工业场景 | Unity Asset Store

NPC智能行为

在之前的博客,已经实现了NPC的部分智能行为,包括了随机搜索以及跟踪玩家的行为。在这里,我将添加巡逻,警戒,躲藏、战术编队等行为。

巡逻警戒

首先是实现巡逻功能,这个可以通过定义巡逻路线经过的关键点,然后利用Unity自带的寻路功能来实现。为此,我们需要对场景的道路进行烘培,点击Window->AI->Navigation,然后选择Bake选项,对场景的可导航路线进行烘培。烘培完成后,需要给Enemy这个预制件增加一个NavMesh Agent的组件,然后在代码中就可以指定目标点的坐标,让Agent自己导航到目的地。

其次是增加警戒模式,这个模式比较简单,就是传入一个警戒点的坐标,然后敌人就在警戒点不定期的随机搜索四周。以下是对WanderingAI的代码进行修改,增加巡逻和警戒这两个行为:

[Header("Enemy behavior")]
...
public bool patrolBehavior = false;
public Vector3[] patrolPoints = null;
public bool guardBehavior = false;
public float guardAngle = 60f;
public float guardMaxRotatePeriod = 10.0f;
public float initialGuardAngle = 0f;

private long _guardTS = 0;
private float _guardChangeTime = 0;

[Flags]
private enum EnemyStatus {  
    ...
    Patrol,
    Guard
}

void Start()
{
    _animator = GetComponent<Animator>();
    muzzleEffect = GetComponent<MuzzleEffect>();
    _agent = GetComponent<NavMeshAgent>();
    currentAmmo = ammo;
    if (patrolBehavior && patrolPoints.Length >= 2) {
        status = EnemyStatus.Patrol;
        _agent.autoBraking = false;
        _agent.destination = patrolPoints[destPoint];
        transform.forward = patrolPoints[destPoint] - patrolPoints[0];
        _animator.SetTrigger("E_Walk");
    } else if (guardBehavior) {
        status = EnemyStatus.Guard;
        transform.localEulerAngles = new Vector3(0f, initialGuardAngle, 0f);
        _guardTS = DateTime.UtcNow.Ticks;
        _guardChangeTime = UnityEngine.Random.Range(1.0f, guardMaxRotatePeriod);
        _animator.SetTrigger("E_Guard");
    } else {
        status = EnemyStatus.Idle;
    }
}

// Update is called once per frame
void Update()
{        
    if (status == EnemyStatus.AimLeft || status == EnemyStatus.AimRight) {
        AimMove();
    } else if (status == EnemyStatus.Reload || status == EnemyStatus.Death) {
        return;
    } else if (status == EnemyStatus.Aim) {
        TurnToPlayer();
    } else if (status == EnemyStatus.Hide) {
        Hide();
    } else if (status == EnemyStatus.Damage) {
        TurnToDamage();
        if (!_animator.GetBool("E_IsDamage")) {
            status = EnemyStatus.Idle;
            prevPlayerPosition = new Vector3(100f, 100f, 100f);
        }
    } else {
        if (status == EnemyStatus.Walk) {
            Walk();
        }
        if (status == EnemyStatus.Sprint) {
            Sprint();
        }
        if (status == EnemyStatus.Patrol) {
            Patrol();
        }
        if (status == EnemyStatus.Guard) {
            Guard();
        }
        DetectPlayer();
    }
}

void Patrol() {
    if (!_agent.pathPending && _agent.remainingDistance < 0.5f) {
        Vector3 prevPosition = patrolPoints[destPoint];
        destPoint = (destPoint + 1) % patrolPoints.Length;
        _agent.destination = patrolPoints[destPoint];
        transform.forward = patrolPoints[destPoint] - prevPosition;
    }
}

public void SetPatrolPoints(Vector3[] points) {
    patrolPoints = points;
}

private void Guard() {
    float interval = (DateTime.UtcNow.Ticks - _guardTS)/10000000.0f;
    if (interval >= _guardChangeTime) {
        _guardTS = DateTime.UtcNow.Ticks;
        _guardChangeTime = UnityEngine.Random.Range(1.0f, guardMaxRotatePeriod);
        float rotateAngle = UnityEngine.Random.Range(-guardAngle, guardAngle);
        transform.localEulerAngles = new Vector3(0f, initialGuardAngle + rotateAngle, 0f);
    }
}

从以上代码可以看到,要设定敌人的行为是巡逻,需要传入巡逻点的坐标,然后依次把巡逻点的坐标设置为Agent的目的地即可,在巡逻的过程中,敌人同样需要检测玩家,如果发现玩家则改变为瞄准行为,这个和之前的随机搜索的行为切换是保持一致的。当行为是警戒时,将随机不定时的转动一些角度来探测玩家。

装弹躲藏

进一步改进敌人在交战时的行为,当敌人打完子弹时,现在的行为是站定了换子弹,为了提高难度,我们可以设计当敌人打完子弹,自动跑到一些隐藏点来重新装弹,之后再出来和玩家交战。为此我们需要设计一些隐藏点。我采取的方法是在场景中选取一些隐藏点,在每个地点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gzroy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值