日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Unity3D之主角面朝方向一定区域内对象角度计算(转)

發(fā)布時(shí)間:2025/3/15 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity3D之主角面朝方向一定区域内对象角度计算(转) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

寫在前面的話,前兩天有個(gè)朋友在QQ上問(wèn)我 如何獲取主角面朝方向一定區(qū)域中的敵人對(duì)象。這個(gè)命題看似簡(jiǎn)單,其實(shí)里面蘊(yùn)含了很多數(shù)學(xué)方面的東西。今天剛好有時(shí)間我就徹底的把這個(gè)疑問(wèn)寫在博客中。希望可以幫助到他。

?

在上代碼之前請(qǐng)大家跟我先做幾個(gè)簡(jiǎn)單的練習(xí)題,角度向量的計(jì)算一定要學(xué)會(huì),不然后面的東西會(huì)很難懂。

?


1.已知3D坐標(biāo),和一個(gè)旋轉(zhuǎn)角度,以及一段距離,求目標(biāo)點(diǎn)的3D坐標(biāo)。

已知當(dāng)前點(diǎn)為Target,目標(biāo)點(diǎn)沿著Target的Y軸旋轉(zhuǎn)30度,沿著Target的X軸延伸10米求目標(biāo)點(diǎn)的3D坐標(biāo)?

?

  • using UnityEngine;
  • using System.Collections;
  • public class Test : MonoBehaviour
  • {
  • ? ?? ???public Transform Target;
  • ? ?? ???void LateUpdate ()
  • ? ?? ???{
  • ? ?? ?? ?? ?? ? Quaternion rotation = Quaternion.Euler(0f,30f,0f) * Target.rotation;
  • ? ?? ?? ?? ?? ? Vector3??newPos = rotation * new Vector3(10f,0f,0f);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(newPos,Vector3.zero,Color.red);
  • ? ?? ?? ?? ?? ? Debug.Log("newpos " + newPos +" nowpos " + Target.position + " distance " + Vector3.Distance(newPos,Target.position));
  • ? ?? ???}
  • }
  • 輸出結(jié)果 :新坐標(biāo) (8.7, 0.0, -5.0) 當(dāng)前坐標(biāo) (0.0, 0.0, 0.0)兩點(diǎn)之間的距離 10。

    ?2.已知3D模型的角度求它的向量。已知3D模型Target,Y軸旋轉(zhuǎn)30度后向前平移。

  • using UnityEngine;
  • using System.Collections;
  • public class Test : MonoBehaviour
  • {
  • ? ?? ???public Transform Target;
  • ? ?? ???void LateUpdate ()
  • ? ?? ???{
  • ? ?? ?? ?? ?? ? if(Input.GetMouseButton(0))
  • ? ?? ?? ?? ?? ? {
  • ? ?? ?? ?? ?? ?? ?? ?? ?Quaternion rotation = Quaternion.Euler(0f,30f,0f) * Target.rotation;
  • ? ?? ?? ?? ?? ?? ?? ?? ?Vector3??newPos = rotation * Vector3.forward;
  • ? ?? ?? ?? ?? ?? ?? ?? ?Target.Translate(newPos.x,newPos.y,newPos.z);
  • ? ?? ?? ?? ?? ? }
  • ? ?? ???}
  • }
  • 3.已知一個(gè)目標(biāo)點(diǎn),讓模型朝著這個(gè)目標(biāo)點(diǎn)移動(dòng)。這是一個(gè)比較簡(jiǎn)單的例子,大家應(yīng)該都能看明白。
  • Target.transform.LookAt(new Vector3 (100f,200f,300f));
  • ? ?? ?? ?? ?? ? Target.Translate(Vector3.forward);
  • 這里我要說(shuō)的就是Vector3.forward ,它等價(jià)與 new Vector3(0,0,1);它并不是一個(gè)坐標(biāo),它是一個(gè)標(biāo)準(zhǔn)向量,方向是沿著Z軸向前。這樣平移一次的距離就是1米, 如果Vector3.forward * 100那么一次平移的距離就是100米。?在看看下面這段代碼.
  • Vector3 vecn = (TargetCube.position - Target.position).normalized;
  • ? ?? ?? ?? ?? ? Target.Translate(vecn *0.1f);
  • 用向量減去一個(gè)向量求出它們的差值,normalized 是格式化向量,意思是把它們之間向量格式化到1米內(nèi)。這樣就可以更加精確的計(jì)算一次平移的距離了 vecn *0.1f 就標(biāo)示一次平移1分米,蛤蛤。?向量不僅可以進(jìn)行X Y Z軸的移動(dòng),同樣可以進(jìn)行旋轉(zhuǎn) ,下面這段代碼就是讓向量沿著Y軸旋轉(zhuǎn)30度。
  • Vector3 vecn = (TargetCube.position - Target.position).normalized;
  • ? ?? ???vecn = Quaternion.Euler(0f,30f,0f) * vecn;
  • ? ?? ???Target.Translate(vecn *0.1f);
  • 如果上述三道簡(jiǎn)單的練習(xí)題 你都能了然于心的話,那么本文最大的難題我相信也不會(huì)是什么難事,繼續(xù)閱讀吧。假設(shè)我們需要計(jì)算主角面前5米內(nèi)所有的對(duì)象時(shí)。以主角為圓心計(jì)算面前5米外的一個(gè)點(diǎn),為了讓大家看清楚我現(xiàn)將這條線繪制出來(lái)。
  • private float distance = 5f;
  • void Update ()?
  • {
  • ? ?? ???Quaternion r= transform.rotation;
  • ? ?? ???Vector3 f0 =??(transform.position??+ (r *Vector3.forward) * distance);
  • ? ?? ???Debug.DrawLine(transform.position,f0,Color.red);
  • }
  • 如下圖所,我們已經(jīng)將這兩個(gè)點(diǎn)計(jì)算出來(lái)了。此時(shí)你可以動(dòng)態(tài)的編輯主角Y軸的坐標(biāo),這個(gè)點(diǎn)永遠(yuǎn)都是沿著主角當(dāng)前角度面前5米以外的點(diǎn)。?

    <ignore_js_op>?
    接下來(lái),我們需要計(jì)算主角面前的一個(gè)發(fā)散性的角度。假設(shè)主角看到的是向左30度,向右30度在這個(gè)區(qū)域。
  • private float distance = 5f;
  • void Update ()?
  • {
  • ? ?? ???Quaternion r= transform.rotation;
  • ? ?? ???Vector3 f0 =??(transform.position??+ (r *Vector3.forward) * distance);
  • ? ?? ???Debug.DrawLine(transform.position,f0,Color.red);
  • ? ?? ???Quaternion r0= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y - 30f,transform.rotation.eulerAngles.z);
  • ? ?? ???Quaternion r1= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y + 30f,transform.rotation.eulerAngles.z);
  • ? ?? ???Vector3 f1 =??(transform.position??+ (r0 *Vector3.forward) * distance);
  • ? ?? ???Vector3 f2 =??(transform.position??+ (r1 *Vector3.forward) * distance);
  • ? ?? ???Debug.DrawLine(transform.position,f1,Color.red);
  • ? ?? ???Debug.DrawLine(transform.position,f2,Color.red);
  • ? ?? ???Debug.DrawLine(f0,f1,Color.red);
  • ? ?? ???Debug.DrawLine(f0,f2,Color.red);
  • }
  • 如下圖所示,這時(shí)主角面前的區(qū)域就計(jì)算出來(lái)了。看起來(lái)就是兩個(gè)三角形之間的區(qū)域。<ignore_js_op>???

    最后就是簡(jiǎn)單的套用公式,計(jì)算一個(gè)點(diǎn)是否在三角形內(nèi),在本文中就是計(jì)算敵人的點(diǎn)是否在面前的這兩個(gè)三角形內(nèi)。
  • using UnityEngine;
  • using System.Collections;
  • public class MyTest : MonoBehaviour {
  • ? ?? ???public Transform cube;
  • ? ?? ???private float distance = 5f;
  • ? ?? ???void Update ()?
  • ? ?? ???{
  • ? ?? ?? ?? ?? ? Quaternion r= transform.rotation;
  • ? ?? ?? ?? ?? ? Vector3 f0 =??(transform.position??+ (r *Vector3.forward) * distance);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(transform.position,f0,Color.red);
  • ? ?? ?? ?? ?? ? Quaternion r0= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y - 30f,transform.rotation.eulerAngles.z);
  • ? ?? ?? ?? ?? ? Quaternion r1= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y + 30f,transform.rotation.eulerAngles.z);
  • ? ?? ?? ?? ?? ? Vector3 f1 =??(transform.position??+ (r0 *Vector3.forward) * distance);
  • ? ?? ?? ?? ?? ? Vector3 f2 =??(transform.position??+ (r1 *Vector3.forward) * distance);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(transform.position,f1,Color.red);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(transform.position,f2,Color.red);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(f0,f1,Color.red);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(f0,f2,Color.red);
  • ? ?? ?? ?? ?? ? Vector3 point = cube.position;
  • ? ?? ?? ?? ?? ? if(isINTriangle(point,transform.position,f1,f0) || isINTriangle(point,transform.position,f2,f0) )
  • ? ?? ?? ?? ?? ? {
  • ? ?? ?? ?? ?? ?? ?? ?? ?Debug.Log("cube in this !!!");
  • ? ?? ?? ?? ?? ? }else?
  • ? ?? ?? ?? ?? ? {
  • ? ?? ?? ?? ?? ?? ?? ?? ?Debug.Log("cube not in this !!!");
  • ? ?? ?? ?? ?? ? }
  • ? ?? ???}
  • ? ?? ???private??float triangleArea(float v0x,float v0y,float v1x,float v1y,float v2x,float v2y)?
  • ? ?? ???{
  • ? ?? ???return Mathf.Abs((v0x * v1y + v1x * v2y + v2x * v0y
  • ? ?? ?? ?? ?- v1x * v0y - v2x * v1y - v0x * v2y) / 2f);
  • ? ? }
  • ? ?? ???bool isINTriangle(Vector3 point,Vector3 v0,Vector3 v1,Vector3 v2)
  • ? ?? ???{
  • ? ?? ?? ?? ?? ? float x = point.x;
  • ? ?? ?? ?? ?? ? float y = point.z;
  • ? ?? ?? ?? ?? ? float v0x = v0.x;
  • ? ?? ?? ?? ?? ? float v0y = v0.z;
  • ? ?? ?? ?? ?? ? float v1x = v1.x;
  • ? ?? ?? ?? ?? ? float v1y = v1.z;
  • ? ?? ?? ?? ?? ? float v2x = v2.x;
  • ? ?? ?? ?? ?? ? float v2y = v2.z;
  • ? ?? ?? ?? ?? ? float t = triangleArea(v0x,v0y,v1x,v1y,v2x,v2y);
  • ? ?? ?? ?? ?? ? float a = triangleArea(v0x,v0y,v1x,v1y,x,y) + triangleArea(v0x,v0y,x,y,v2x,v2y) + triangleArea(x,y,v1x,v1y,v2x,v2y);
  • ? ?? ?? ?? ?? ? if (Mathf.Abs(t - a) <= 0.01f)?
  • ? ?? ?? ?? ?? ? {
  • ? ?? ?? ?? ?? ?? ?? ?? ?return true;
  • ? ?? ?? ?? ?? ? }else?
  • ? ?? ?? ?? ?? ? {
  • ? ?? ?? ?? ?? ?? ?? ?? ?return false;
  • ? ?? ?? ?? ?? ? }
  • ? ?? ???}
  • }
  • 如下圖所示,如果箱子對(duì)象是主角的視野中就會(huì)檢測(cè)到。


    <ignore_js_op>???

    注意,上圖中我的視野選擇了兩個(gè)三角形,如果你需要視野目標(biāo)點(diǎn)是橢圓形的話,那么可以多設(shè)置一些三角形。但是這樣就會(huì)非常消耗效率,我覺(jué)得這里完全可以使用1個(gè)三角形,,只是正對(duì)的目標(biāo)點(diǎn)會(huì)出現(xiàn)一些偏差,影響其實(shí)并不會(huì)很大。如下圖所示


    <ignore_js_op>?


    碼簡(jiǎn)單的修改一下即可。
  • using UnityEngine;
  • using System.Collections;
  • public class MyTest : MonoBehaviour {
  • ? ?? ???public Transform cube;
  • ? ?? ???private float distance = 5f;
  • ? ?? ???void Update ()?
  • ? ?? ???{
  • ? ?? ?? ?? ?? ? Quaternion r= transform.rotation;
  • ? ?? ?? ?? ?? ? Vector3 f0 =??(transform.position??+ (r *Vector3.forward) * distance);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(transform.position,f0,Color.red);
  • ? ?? ?? ?? ?? ? Quaternion r0= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y - 30f,transform.rotation.eulerAngles.z);
  • ? ?? ?? ?? ?? ? Quaternion r1= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y + 30f,transform.rotation.eulerAngles.z);
  • ? ?? ?? ?? ?? ? Vector3 f1 =??(transform.position??+ (r0 *Vector3.forward) * distance);
  • ? ?? ?? ?? ?? ? Vector3 f2 =??(transform.position??+ (r1 *Vector3.forward) * distance);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(transform.position,f1,Color.red);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(transform.position,f2,Color.red);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(f1,f2,Color.red);
  • ? ?? ?? ?? ?? ? Vector3 point = cube.position;
  • ? ?? ?? ?? ?? ? if(isINTriangle(point,transform.position,f1,f2))
  • ? ?? ?? ?? ?? ? {
  • ? ?? ?? ?? ?? ?? ?? ?? ?Debug.Log("cube in this !!!");
  • ? ?? ?? ?? ?? ? }else?
  • ? ?? ?? ?? ?? ? {
  • ? ?? ?? ?? ?? ?? ?? ?? ?Debug.Log("cube not in this !!!");
  • ? ?? ?? ?? ?? ? }
  • ? ?? ???}
  • ? ?? ???private??float triangleArea(float v0x,float v0y,float v1x,float v1y,float v2x,float v2y)?
  • ? ?? ???{
  • ? ?? ???return Mathf.Abs((v0x * v1y + v1x * v2y + v2x * v0y
  • ? ?? ?? ?? ?- v1x * v0y - v2x * v1y - v0x * v2y) / 2f);
  • ? ? }
  • ? ?? ???bool isINTriangle(Vector3 point,Vector3 v0,Vector3 v1,Vector3 v2)
  • ? ?? ???{
  • ? ?? ?? ?? ?? ? float x = point.x;
  • ? ?? ?? ?? ?? ? float y = point.z;
  • ? ?? ?? ?? ?? ? float v0x = v0.x;
  • ? ?? ?? ?? ?? ? float v0y = v0.z;
  • ? ?? ?? ?? ?? ? float v1x = v1.x;
  • ? ?? ?? ?? ?? ? float v1y = v1.z;
  • ? ?? ?? ?? ?? ? float v2x = v2.x;
  • ? ?? ?? ?? ?? ? float v2y = v2.z;
  • ? ?? ?? ?? ?? ? float t = triangleArea(v0x,v0y,v1x,v1y,v2x,v2y);
  • ? ?? ?? ?? ?? ? float a = triangleArea(v0x,v0y,v1x,v1y,x,y) + triangleArea(v0x,v0y,x,y,v2x,v2y) + triangleArea(x,y,v1x,v1y,v2x,v2y);
  • ? ?? ?? ?? ?? ? if (Mathf.Abs(t - a) <= 0.01f)?
  • ? ?? ?? ?? ?? ? {
  • ? ?? ?? ?? ?? ?? ?? ?? ?return true;
  • ? ?? ?? ?? ?? ? }else?
  • ? ?? ?? ?? ?? ? {
  • ? ?? ?? ?? ?? ?? ?? ?? ?return false;
  • ? ?? ?? ?? ?? ? }
  • ? ?? ???}
  • }
  • 上面我們介紹了三角形判斷,當(dāng)然也可以通過(guò)矩形來(lái)判斷是否相交。。


    <ignore_js_op>?

    代碼:
  • using UnityEngine;
  • using System.Collections;
  • public class MyTest : MonoBehaviour {
  • ? ?? ???public Transform cube;
  • ? ?? ???private float distance = 5f;
  • ? ?? ???void Update ()?
  • ? ?? ???{
  • ? ?? ?? ?? ?? ? Quaternion r= transform.rotation;
  • ? ?? ?? ?? ?? ? Vector3 left =??(transform.position??+ (r *Vector3.left) * distance);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(transform.position,left,Color.red);
  • ? ?? ?? ?? ?? ? Vector3 right =??(transform.position??+ (r *Vector3.right) * distance);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(transform.position,right,Color.red);
  • ? ?? ?? ?? ?? ? Vector3 leftEnd = (left??+ (r *Vector3.forward) * distance);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(left,leftEnd,Color.red);
  • ? ?? ?? ?? ?? ? Vector3 rightEnd = (right??+ (r *Vector3.forward) * distance);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(right,rightEnd,Color.red);
  • ? ?? ?? ?? ?? ? Debug.DrawLine(leftEnd,rightEnd,Color.red);
  • ? ?? ?? ?? ?? ? Vector3 point = cube.position;
  • ? ?? ?? ?? ?? ? if(isINRect(point,leftEnd,rightEnd,right,left))
  • ? ?? ?? ?? ?? ? {
  • ? ?? ?? ?? ?? ?? ?? ?? ?Debug.Log("cube in this !!!");
  • ? ?? ?? ?? ?? ? }else?
  • ? ?? ?? ?? ?? ? {
  • ? ?? ?? ?? ?? ?? ?? ?? ?Debug.Log("cube not in this !!!");
  • ? ?? ?? ?? ?? ? }
  • ? ?? ???}
  • ? ???private float Multiply(float p1x , float p1y, float p2x,float p2y, float p0x,float p0y)
  • ? ???{
  • ? ?? ???return ((p1x - p0x) * (p2y - p0y) - (p2x - p0x) * (p1y - p0y));
  • ? ???}
  • ? ?? ???bool isINRect(Vector3 point,Vector3 v0,Vector3 v1,Vector3 v2,Vector3 v3)
  • ? ?? ???{
  • ? ?? ?? ?? ?? ? float x = point.x;
  • ? ?? ?? ?? ?? ? float y = point.z;
  • ? ?? ?? ?? ?? ? float v0x = v0.x;
  • ? ?? ?? ?? ?? ? float v0y = v0.z;
  • ? ?? ?? ?? ?? ? float v1x = v1.x;
  • ? ?? ?? ?? ?? ? float v1y = v1.z;
  • ? ?? ?? ?? ?? ? float v2x = v2.x;
  • ? ?? ?? ?? ?? ? float v2y = v2.z;
  • ? ?? ?? ?? ?? ? float v3x = v3.x;
  • ? ?? ?? ?? ?? ? float v3y = v3.z;
  • ? ?? ?? ?? ?? ? if (Multiply(x,y, v0x,v0y, v1x,v1y) * Multiply(x,y, v3x,v3y, v2x,v2y) <= 0 && Multiply(x,y, v3x,v3y, v0x,v0y) * Multiply(x,y, v2x,v2y, v1x,v1y) <= 0)
  • ? ?? ?? ?? ? return true;
  • ? ?? ?? ?? ?? ? else
  • ? ?? ?? ?? ?return false;
  • ? ?? ???}
  • }
  • 如果大家看了這篇文章后發(fā)現(xiàn)在你的項(xiàng)目中還有一些比較麻煩的角度與向量的算法,歡迎在下面留言給我,如果我有時(shí)間我會(huì)第一時(shí)間把方法貼在博客中。互相學(xué)習(xí)互相進(jìn)步,加油!哇咔咔。。馬上過(guò)年了,雨松MOMO在這里祝福大家2013年幸幸福福的過(guò)日子,嘿嘿。?


    2013年4月補(bǔ)充感謝樓下朋友給我的留言。, 我在補(bǔ)充一下這篇博客。
  • using UnityEngine;
  • using System.Collections;
  • public class NewBehaviourScript : MonoBehaviour {
  • ? ?? ???public Transform target;
  • ? ?? ???void Update()
  • ? ?? ???{
  • ? ?? ?? ?? ?? ?? ?? ?? ?float distance = Vector3.Distance(target.position,transform.position);
  • ? ?? ?? ?? ?? ?? ?? ?? ?Quaternion right? ?? ?? ?= transform.rotation * Quaternion.AngleAxis(30,Vector3.up);
  • ? ?? ?? ?? ?? ?? ?? ?? ?Quaternion left? ?? ?? ?= transform.rotation * Quaternion.AngleAxis(30,Vector3.down);
  • ? ?? ?? ?? ?? ?? ?? ?? ?Vector3 n =? ?? ?? ?transform.position + (Vector3.forward * distance);
  • ? ?? ?? ?? ?? ?? ?? ?? ?Vector3 leftPoint = left *? ?? ?? ?n ;
  • ? ?? ?? ?? ?? ?? ?? ?? ?Vector3 rightPoint =??right *n ;
  • ? ?? ?? ?? ?? ?? ?? ?? ?Debug.DrawLine(transform.position,leftPoint,Color.red);
  • ? ?? ?? ?? ?? ?? ?? ?? ?Debug.DrawLine(transform.position,rightPoint,Color.red);
  • ? ?? ?? ?? ?? ?? ?? ?? ?Debug.DrawLine(rightPoint,leftPoint,Color.red);
  • ? ?? ???}
  • }
  • <ignore_js_op>?




    里我以角色左右個(gè)30度。 這樣就可以根據(jù)兩個(gè)模型的距離以及角度來(lái)判斷了。。

    轉(zhuǎn)載于:https://www.cnblogs.com/weiqiangwaideshijie/p/6632922.html

    總結(jié)

    以上是生活随笔為你收集整理的Unity3D之主角面朝方向一定区域内对象角度计算(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。