unity3d 工程原理_技术贴:0经验上手手游Unity3D开发

本文介绍了一个Unity3D中的敌人视线系统,使用NavMeshAgent和SphereCollider组件来检测玩家是否在敌人的视野范围内。通过Raycast判断角度和视线距离,当玩家在视野内时更新其位置信息,并影响角色动画状态。同时,实现了一个计算目标与敌人之间路径长度的方法。
摘要由CSDN通过智能技术生成

using UnityEngine;

using System.Collections;

public class DoneEnemySight : MonoBehaviour

{

public float fieldOfViewAngle = 110f;               // Number of degrees, centred on forward, for the enemy see.

public bool playerInSight;                          // Whether or not the player is currently sighted.

public Vector3 personalLastSighting;                // Last place this enemy spotted the player.

private NavMeshAgent nav;                           // Reference to the NavMeshAgent component.

private SphereCollider col;                         // Reference to the sphere collider trigger component.

private Animator anim;                              // Reference to the Animator.

private DoneLastPlayerSighting lastPlayerSighting;  // Reference to last global sighting of the player.

private GameObject player;                          // Reference to the player.

private Animator playerAnim;                        // Reference to the player's animator component.

private DonePlayerHealth playerHealth;              // Reference to the player's health script.

private DoneHashIDs hash;                           // Reference to the HashIDs.

private Vector3 previousSighting;                   // Where the player was sighted last frame.

void Awake ()

{

// Setting up the references.

nav = GetComponent();

col = GetComponent();

anim = GetComponent();

lastPlayerSighting = GameObject.FindGameObjectWithTag(DoneTags.gameController).GetComponent();

player = GameObject.FindGameObjectWithTag(DoneTags.player);

playerAnim = player.GetComponent();

playerHealth = player.GetComponent();

hash = GameObject.FindGameObjectWithTag(DoneTags.gameController).GetComponent();

// Set the personal sighting and the previous sighting to the reset position.

personalLastSighting = lastPlayerSighting.resetPosition;

previousSighting = lastPlayerSighting.resetPosition;

}

void Update ()

{

// If the last global sighting of the player has changed...

if(lastPlayerSighting.position != previousSighting)

// ... then update the personal sighting to be the same as the global sighting.

personalLastSighting = lastPlayerSighting.position;

// Set the previous sighting to the be the sighting from this frame.

previousSighting = lastPlayerSighting.position;

// If the player is alive...

if(playerHealth.health > 0f)

// ... set the animator parameter to whether the player is in sight or not.

anim.SetBool(hash.playerInSightBool, playerInSight);

else

// ... set the animator parameter to false.

anim.SetBool(hash.playerInSightBool, false);

}

void OnTriggerStay (Collider other)

{

// If the player has entered the trigger sphere...

if(other.gameObject == player)

{

// By default the player is not in sight.

playerInSight = false;

// Create a vector from the enemy to the player and store the angle between it and forward.

Vector3 direction = other.transform.position - transform.position;

float angle = Vector3.Angle(direction, transform.forward);

// If the angle between forward and where the player is, is less than half the angle of view...

if(angle < fieldOfViewAngle * 0.5f)

{

RaycastHit hit;

// ... and if a raycast towards the player hits something...

if(Physics.Raycast(transform.position + transform.up, direction.normalized, out hit, col.radius))

{

// ... and if the raycast hits the player...

if(hit.collider.gameObject == player)

{

// ... the player is in sight.

playerInSight = true;

// Set the last global sighting is the players current position.

lastPlayerSighting.position = player.transform.position;

}

}

}

// Store the name hashes of the current states.

int playerLayerZeroStateHash = playerAnim.GetCurrentAnimatorStateInfo(0).nameHash;

int playerLayerOneStateHash = playerAnim.GetCurrentAnimatorStateInfo(1).nameHash;

// If the player is running or is attracting attention...

if(playerLayerZeroStateHash == hash.locomotionState || playerLayerOneStateHash == hash.shoutState)

{

// ... and if the player is within hearing range...

if(CalculatePathLength(player.transform.position) <= col.radius)

// ... set the last personal sighting of the player to the player's current position.

personalLastSighting = player.transform.position;

}

}

}

void OnTriggerExit (Collider other)

{

// If the player leaves the trigger zone...

if(other.gameObject == player)

// ... the player is not in sight.

playerInSight = false;

}

float CalculatePathLength (Vector3 targetPosition)

{

// Create a path and set it based on a target position.

NavMeshPath path = new NavMeshPath();

if(nav.enabled)

nav.CalculatePath(targetPosition, path);

// Create an array of points which is the length of the number of corners in the path + 2.

Vector3 [] allWayPoints = new Vector3[path.corners.Length + 2];

// The first point is the enemy's position.

allWayPoints[0] = transform.position;

// The last point is the target position.

allWayPoints[allWayPoints.Length - 1] = targetPosition;

// The points inbetween are the corners of the path.

for(int i = 0; i < path.corners.Length; i++)

{

allWayPoints[i + 1] = path.corners[i];

}

// Create a float to store the path length that is by default 0.

float pathLength = 0;

// Increment the path length by an amount equal to the distance between each waypoint and the next.

for(int i = 0; i < allWayPoints.Length - 1; i++)

{

pathLength += Vector3.Distance(allWayPoints[i], allWayPoints[i + 1]);

}

return pathLength;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值