判断角色是否在玩家可见范围之内

本文探讨了如何在Unity中实现NPC视角范围限制及观察距离判断,通过向量运算和角度计算,解释了如何利用点积和叉积确定角色B是否在玩家A的可视范围内,涉及向量模、夹角和相关数学原理的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

玩家A的可视角度为θ,可视半径为R 

已知玩家A和角色B的位置和朝向

判断角色B是否在玩家A的可视距离之内

算法

在可视范围内,需要满足两个条件: 

① |AB| <=R

② 向量AB与V的夹角 <= θ/2

代码(调库)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SectorJudge : MonoBehaviour
{
    public GameObject target;

    public float R;

    public float theta;

    // Update is called once per frame
    void Update()
    {
        isVisible(R,theta,target);
    }

    bool isVisible(float R, float theta,GameObject target)
    {
        if((target.transform.position-transform.position).magnitude>R)
        {
            print("不在可视距离内");
            return false;
        }

        if(Vector3.Angle(transform.forward,(target.transform.position - transform.position))>(theta/2))//须使用transform.forward,而非Vector3.forward
        {
            print("不在可视角度内");
            return false;
        }

        return true;
    }
}

解析

求向量AB的模 |AB|

(target.transform.position-transform.position).magnitude

求向量AB与V的夹角

Vector3.Angle(transform.forward,(target.transform.position - transform.position)

相关数学知识

1. 求向量的模

2. 求向量的夹角

a·b=|a||b|cosθ

3. 点积(数量积)

代码(手撕)

using System;
using UnityEngine;

public class SectorJudge : MonoBehaviour
{
    public GameObject target;

    public double R;

    public double theta;

    // Update is called once per frame
    void Update()
    {
        isVisible(R,theta,target);
    }

    bool isVisible(double R, double theta, GameObject target)
    {
        if(Magnitude(target.transform.position - transform.position) > R)
        {
            print("不在可视距离内");
            return false;
        }

        if(Angle(transform.forward, (target.transform.position - transform.position)) >(theta/2))
        {
            print("不在可视角度内");
            return false;
        }

        return true;
    }

    double Magnitude(Vector3 a)
    {
        return Math.Sqrt((a.x*a.x)+(a.y*a.y)+(a.z*a.z));
    }

    double Angle(Vector3 a,Vector3 b)
    {
        double costheta = Dot(a,b)/ (Magnitude(a)* Magnitude(b));
        return Math.Acos(costheta)*(180/3.14);
    }

    double Dot(Vector3 a, Vector3 b)
    {
        return a.x * b.x + a.y * b.y + a.z * b.z;
    }
}

解析

点乘的库函数为Vector3.Dot(a,b)

弧度转角度,乘上Mathf.Rad2Deg,其值为180/Pi,约等于57.30

------------------------------------------------------更新------------------------------------------------------

(Unity Shader入门精要,P54)

假设,场景中有一个NPC,它位于点p处, 它的前方可以使用矢量v来表示。

问:如果现在玩家运动到了点x处, 那么如何判断玩家是在NPC的前方还是后方?

请使用数学公式来描述你的答案。

答: 使用点积来判断。

因为a·b=|a||b|cosθ,所以

cosθ = V·PX / |V||PX|;

又因为 V·PX = Vx * PXx + Vy * PXy + Vz * PXz;

如果cosθ大于0,说明θ<90°,在前面

如果cosθ小于0,说明θ>90°,在后面

问:如果现在玩家运动到了点x处, 那么如何判断玩家是在NPC的左边还是右边?

请使用数学公式来描述你的答案。

答: 使用叉积来判断。

因为|a✖️b|=|a||b|sinθ,所以

sinθ = |V✖️PX| / |V||PX|;

又因为 V✖️PX = 按以下方式计算;

如果sinθ大于0,说明0°<θ<180°,在左面

如果sinθ小于0,说明180°<θ<360°,在右面

问:现在游戏有了新的需求:NPC只能观察到有限的视角范围,这个视角的角度是φ,也就是说,NPC最多只能看到它前方左侧或右侧 φ/2角度内的物体。那么我们如何通过点积来判断NPC是否看到点x呢?

答:只需要判断夹角是否小于φ/2即可。

如果arccosθ<φ/2,则看得到

如果arccosθ>φ/2,则看不到

问:在上一问的条件上,策划又有了新的需求:

NPC的观察距离也有了限制,它只能看到固定距离R的对象,现在又该如何判断呢?

答:只需要比较PX与R的大小即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值