first commit
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
using System.Collections;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
public enum OffMeshLinkMoveMethod
|
||||
{
|
||||
Teleport,
|
||||
NormalSpeed,
|
||||
Parabola,
|
||||
Curve
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move an agent when traversing a OffMeshLink given specific animated methods
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(NavMeshAgent))]
|
||||
public class AgentLinkMover : MonoBehaviour
|
||||
{
|
||||
public OffMeshLinkMoveMethod m_Method = OffMeshLinkMoveMethod.Parabola;
|
||||
public AnimationCurve m_Curve = new AnimationCurve();
|
||||
|
||||
IEnumerator Start()
|
||||
{
|
||||
NavMeshAgent agent = GetComponent<NavMeshAgent>();
|
||||
agent.autoTraverseOffMeshLink = false;
|
||||
while (true)
|
||||
{
|
||||
if (agent.isOnOffMeshLink)
|
||||
{
|
||||
if (m_Method == OffMeshLinkMoveMethod.NormalSpeed)
|
||||
yield return StartCoroutine(NormalSpeed(agent));
|
||||
else if (m_Method == OffMeshLinkMoveMethod.Parabola)
|
||||
yield return StartCoroutine(Parabola(agent, 2.0f, 0.5f));
|
||||
else if (m_Method == OffMeshLinkMoveMethod.Curve)
|
||||
yield return StartCoroutine(Curve(agent, 0.5f));
|
||||
agent.CompleteOffMeshLink();
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator NormalSpeed(NavMeshAgent agent)
|
||||
{
|
||||
OffMeshLinkData data = agent.currentOffMeshLinkData;
|
||||
Vector3 endPos = data.endPos + Vector3.up * agent.baseOffset;
|
||||
while (agent.transform.position != endPos)
|
||||
{
|
||||
agent.transform.position =
|
||||
Vector3.MoveTowards(agent.transform.position, endPos, agent.speed * Time.deltaTime);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator Parabola(NavMeshAgent agent, float height, float duration)
|
||||
{
|
||||
OffMeshLinkData data = agent.currentOffMeshLinkData;
|
||||
Vector3 startPos = agent.transform.position;
|
||||
Vector3 endPos = data.endPos + Vector3.up * agent.baseOffset;
|
||||
float normalizedTime = 0.0f;
|
||||
while (normalizedTime < 1.0f)
|
||||
{
|
||||
float yOffset = height * 4.0f * (normalizedTime - normalizedTime * normalizedTime);
|
||||
agent.transform.position = Vector3.Lerp(startPos, endPos, normalizedTime) + yOffset * Vector3.up;
|
||||
normalizedTime += Time.deltaTime / duration;
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator Curve(NavMeshAgent agent, float duration)
|
||||
{
|
||||
OffMeshLinkData data = agent.currentOffMeshLinkData;
|
||||
Vector3 startPos = agent.transform.position;
|
||||
Vector3 endPos = data.endPos + Vector3.up * agent.baseOffset;
|
||||
float normalizedTime = 0.0f;
|
||||
while (normalizedTime < 1.0f)
|
||||
{
|
||||
float yOffset = m_Curve.Evaluate(normalizedTime);
|
||||
agent.transform.position = Vector3.Lerp(startPos, endPos, normalizedTime) + yOffset * Vector3.up;
|
||||
normalizedTime += Time.deltaTime / duration;
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03bc8063c9e95401f9a8a38bc716750d
|
||||
timeCreated: 1460116525
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Use physics raycast hit from mouse click to set agent destination
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(NavMeshAgent))]
|
||||
public class ClickToMove : MonoBehaviour
|
||||
{
|
||||
NavMeshAgent m_Agent;
|
||||
RaycastHit m_HitInfo = new RaycastHit();
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_Agent = GetComponent<NavMeshAgent>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0) && !Input.GetKey(KeyCode.LeftShift))
|
||||
{
|
||||
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||||
if (Physics.Raycast(ray.origin, ray.direction, out m_HitInfo))
|
||||
m_Agent.destination = m_HitInfo.point;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9472e73a59274b9b8da79d72004bd8b
|
||||
timeCreated: 1430734266
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Destroy GameObjects upon collision
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Collider))]
|
||||
public class Despawner : MonoBehaviour
|
||||
{
|
||||
void OnCollisionEnter(Collision collision)
|
||||
{
|
||||
Destroy(collision.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3be0b2e79a40424c88b51776d94b8a5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Destroy owning GameObject if any collider with a specific tag is trespassing
|
||||
/// </summary>
|
||||
public class DestroyOnTrigger : MonoBehaviour
|
||||
{
|
||||
public string m_Tag = "Player";
|
||||
|
||||
void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (other.gameObject.tag == m_Tag)
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c786c4b29e72040b881bf13065fb9788
|
||||
timeCreated: 1430999621
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,56 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize dungeon tiles with a specified width and height
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(-200)]
|
||||
public class DungeonManager : MonoBehaviour
|
||||
{
|
||||
public int m_Width = 10;
|
||||
public int m_Height = 10;
|
||||
public float m_Spacing = 4.0f;
|
||||
public GameObject[] m_Tiles = new GameObject[16];
|
||||
|
||||
void Awake()
|
||||
{
|
||||
Random.InitState(23431);
|
||||
var map = new int[m_Width * m_Height];
|
||||
for (int y = 0; y < m_Height; y++)
|
||||
{
|
||||
for (int x = 0; x < m_Width; x++)
|
||||
{
|
||||
bool px = false;
|
||||
bool py = false;
|
||||
if (x > 0)
|
||||
px = (map[(x - 1) + y * m_Width] & 1) != 0;
|
||||
if (y > 0)
|
||||
py = (map[x + (y - 1) * m_Width] & 2) != 0;
|
||||
|
||||
int tile = 0;
|
||||
if (px)
|
||||
tile |= 4;
|
||||
if (py)
|
||||
tile |= 8;
|
||||
if (x + 1 < m_Width && Random.value > 0.5f)
|
||||
tile |= 1;
|
||||
if (y + 1 < m_Height && Random.value > 0.5f)
|
||||
tile |= 2;
|
||||
|
||||
map[x + y * m_Width] = tile;
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = 0; y < m_Height; y++)
|
||||
{
|
||||
for (int x = 0; x < m_Width; x++)
|
||||
{
|
||||
var pos = new Vector3(x * m_Spacing, 0, y * m_Spacing);
|
||||
if (m_Tiles[map[x + y * m_Width]] != null)
|
||||
Instantiate(m_Tiles[map[x + y * m_Width]], pos, Quaternion.identity, transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c56d911659e3c4b499e11b47a73a4dbb
|
||||
timeCreated: 1430743428
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Component for moving GameObjects within a NavMesh.
|
||||
/// Requests a NavMesh update whenever its owning GameObject has stopped moving.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
[RequireComponent(typeof(NavMeshModifier))]
|
||||
public class DynamicNavMeshObject : MonoBehaviour
|
||||
{
|
||||
Rigidbody m_Rigidbody;
|
||||
NavMeshModifier m_NavMeshModifier;
|
||||
bool m_WasMoving;
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_Rigidbody = GetComponent<Rigidbody>();
|
||||
m_NavMeshModifier = GetComponent<NavMeshModifier>();
|
||||
m_NavMeshModifier.enabled = true;
|
||||
m_WasMoving = !m_Rigidbody.IsSleeping();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
bool isMoving = !m_Rigidbody.IsSleeping() && m_Rigidbody.velocity.sqrMagnitude > 0.1f;
|
||||
|
||||
if ((m_WasMoving && !isMoving) || (!m_WasMoving && isMoving))
|
||||
{
|
||||
m_NavMeshModifier.ignoreFromBuild = isMoving;
|
||||
GloballyUpdatedNavMeshSurface.RequestNavMeshUpdate();
|
||||
}
|
||||
|
||||
m_WasMoving = isMoving;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac596217843ab3647b721eacaea9c581
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables a behaviour when a rigidbody settles movement
|
||||
/// otherwise disables the behaviour
|
||||
/// </summary>
|
||||
public class EnableIffSleeping : MonoBehaviour
|
||||
{
|
||||
public Behaviour m_Behaviour;
|
||||
Rigidbody m_Rigidbody;
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_Rigidbody = GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (m_Rigidbody == null || m_Behaviour == null)
|
||||
return;
|
||||
|
||||
if (m_Rigidbody.IsSleeping() && !m_Behaviour.enabled)
|
||||
m_Behaviour.enabled = true;
|
||||
|
||||
if (!m_Rigidbody.IsSleeping() && m_Behaviour.enabled)
|
||||
m_Behaviour.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c56046daca8eb46f3af030c05f030e37
|
||||
timeCreated: 1431001396
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,64 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Manipulating the camera with standard inputs
|
||||
/// </summary>
|
||||
public class FreeCam : MonoBehaviour
|
||||
{
|
||||
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
|
||||
public RotationAxes axes = RotationAxes.MouseXAndY;
|
||||
public float sensitivityX = 15F;
|
||||
public float sensitivityY = 15F;
|
||||
|
||||
public float minimumX = -360F;
|
||||
public float maximumX = 360F;
|
||||
|
||||
public float minimumY = -60F;
|
||||
public float maximumY = 60F;
|
||||
|
||||
public float moveSpeed = 1.0f;
|
||||
|
||||
public bool lockHeight = false;
|
||||
|
||||
float rotationY = 0F;
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (axes == RotationAxes.MouseXAndY)
|
||||
{
|
||||
float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX;
|
||||
|
||||
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
|
||||
rotationY = Mathf.Clamp(rotationY, minimumY, maximumY);
|
||||
|
||||
transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
|
||||
}
|
||||
else if (axes == RotationAxes.MouseX)
|
||||
{
|
||||
transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
|
||||
rotationY = Mathf.Clamp(rotationY, minimumY, maximumY);
|
||||
|
||||
transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0);
|
||||
}
|
||||
|
||||
var xAxisValue = Input.GetAxis("Horizontal");
|
||||
var zAxisValue = Input.GetAxis("Vertical");
|
||||
if (lockHeight)
|
||||
{
|
||||
var dir = transform.TransformDirection(new Vector3(xAxisValue, 0.0f, zAxisValue) * moveSpeed);
|
||||
dir.y = 0.0f;
|
||||
transform.position += dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.Translate(new Vector3(xAxisValue, 0.0f, zAxisValue) * moveSpeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6c30eb361e754b75ac25325c5d024bd
|
||||
timeCreated: 1430921534
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// NavMeshSurface that updates only once per frame upon request
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(NavMeshSurface))]
|
||||
public class GloballyUpdatedNavMeshSurface : MonoBehaviour
|
||||
{
|
||||
static bool s_NeedsNavMeshUpdate;
|
||||
|
||||
NavMeshSurface m_Surface;
|
||||
|
||||
public static void RequestNavMeshUpdate()
|
||||
{
|
||||
s_NeedsNavMeshUpdate = true;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_Surface = GetComponent<NavMeshSurface>();
|
||||
m_Surface.BuildNavMesh();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (s_NeedsNavMeshUpdate)
|
||||
{
|
||||
m_Surface.UpdateNavMesh(m_Surface.navMeshData);
|
||||
s_NeedsNavMeshUpdate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f48d3001ccdce69418119f74f39f090d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,118 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.AI;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Manipulation tool for displacing the vertices in a list of meshes
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(-101)]
|
||||
public class MeshTool : MonoBehaviour
|
||||
{
|
||||
NavMeshSurface m_Surface;
|
||||
|
||||
public enum ExtrudeMethod
|
||||
{
|
||||
Vertical,
|
||||
MeshNormal
|
||||
}
|
||||
|
||||
public List<MeshFilter> m_Filters = new List<MeshFilter>();
|
||||
public float m_Radius = 1.5f;
|
||||
public float m_Power = 2.0f;
|
||||
public ExtrudeMethod m_Method = ExtrudeMethod.Vertical;
|
||||
|
||||
RaycastHit m_HitInfo = new RaycastHit();
|
||||
AsyncOperation m_LastNavMeshUpdate;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
Cursor.lockState = CursorLockMode.Locked;
|
||||
Cursor.visible = false;
|
||||
|
||||
m_Surface = GetComponent<NavMeshSurface>();
|
||||
if (m_Surface != null)
|
||||
{
|
||||
m_Surface.BuildNavMesh();
|
||||
m_LastNavMeshUpdate = m_Surface.UpdateNavMesh(m_Surface.navMeshData);
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
var ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
|
||||
if (Physics.Raycast(ray.origin, ray.direction, out m_HitInfo))
|
||||
{
|
||||
Debug.DrawRay(m_HitInfo.point, m_HitInfo.normal, Color.red);
|
||||
Vector3 displacement = (m_Method == ExtrudeMethod.Vertical) ? Vector3.up : m_HitInfo.normal;
|
||||
|
||||
if (Input.GetMouseButton(0) || (Input.GetKey(KeyCode.Space) && !Input.GetKey(KeyCode.LeftShift)))
|
||||
{
|
||||
ModifyMesh(m_Power * displacement, m_HitInfo.point);
|
||||
if (m_Surface != null)
|
||||
{
|
||||
if (m_LastNavMeshUpdate.isDone)
|
||||
m_LastNavMeshUpdate = m_Surface.UpdateNavMesh(m_Surface.navMeshData);
|
||||
}
|
||||
|
||||
}
|
||||
else if (Input.GetMouseButton(1) || (Input.GetKey(KeyCode.Space) && Input.GetKey(KeyCode.LeftShift)))
|
||||
{
|
||||
ModifyMesh(-m_Power * displacement, m_HitInfo.point);
|
||||
if(m_Surface != null)
|
||||
{
|
||||
if (m_LastNavMeshUpdate.isDone)
|
||||
m_LastNavMeshUpdate = m_Surface.UpdateNavMesh(m_Surface.navMeshData);
|
||||
}
|
||||
}
|
||||
else if(Input.GetMouseButtonUp(0) || Input.GetMouseButtonUp(1) || Input.GetKeyUp(KeyCode.Space))
|
||||
{
|
||||
if (m_Surface != null)
|
||||
{
|
||||
if (!m_LastNavMeshUpdate.isDone)
|
||||
NavMeshBuilder.Cancel(m_Surface.navMeshData);
|
||||
|
||||
m_LastNavMeshUpdate = m_Surface.UpdateNavMesh(m_Surface.navMeshData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModifyMesh(Vector3 displacement, Vector3 center)
|
||||
{
|
||||
foreach (var filter in m_Filters)
|
||||
{
|
||||
Mesh mesh = filter.mesh;
|
||||
Vector3[] vertices = mesh.vertices;
|
||||
|
||||
for (int i = 0; i < vertices.Length; ++i)
|
||||
{
|
||||
Vector3 v = filter.transform.TransformPoint(vertices[i]);
|
||||
vertices[i] = vertices[i] + displacement * Gaussian(v, center, m_Radius);
|
||||
}
|
||||
|
||||
mesh.vertices = vertices;
|
||||
mesh.RecalculateBounds();
|
||||
|
||||
var col = filter.GetComponent<MeshCollider>();
|
||||
if (col != null)
|
||||
{
|
||||
var colliMesh = new Mesh();
|
||||
colliMesh.vertices = mesh.vertices;
|
||||
colliMesh.triangles = mesh.triangles;
|
||||
col.sharedMesh = colliMesh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static float Gaussian(Vector3 pos, Vector3 mean, float dev)
|
||||
{
|
||||
float x = pos.x - mean.x;
|
||||
float y = pos.y - mean.y;
|
||||
float z = pos.z - mean.z;
|
||||
float n = 1.0f / (2.0f * Mathf.PI * dev * dev);
|
||||
return n * Mathf.Pow(2.718281828f, -(x * x + y * y + z * z) / (2.0f * dev * dev));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d5a3e609186342b2a976cd32fd7d0f0
|
||||
timeCreated: 1430920188
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Update a NavMeshSurface with Volume object collection
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(-102)]
|
||||
public class NavMeshSurfaceVolumeUpdater : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
NavMeshAgent trackedAgent;
|
||||
|
||||
NavMeshSurface m_Surface;
|
||||
Vector3 m_VolumeSize;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
m_Surface = GetComponent<NavMeshSurface>();
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_VolumeSize = m_Surface.size;
|
||||
m_Surface.center = QuantizedCenter();
|
||||
m_Surface.BuildNavMesh();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
UpdateNavMeshOnCenterOrSizeChange();
|
||||
}
|
||||
|
||||
void UpdateNavMeshOnCenterOrSizeChange()
|
||||
{
|
||||
var updatedCenter = QuantizedCenter();
|
||||
var updateNavMesh = false;
|
||||
|
||||
if (m_Surface.center != updatedCenter)
|
||||
{
|
||||
m_Surface.center = updatedCenter;
|
||||
updateNavMesh = true;
|
||||
}
|
||||
|
||||
if (m_Surface.size != m_VolumeSize)
|
||||
{
|
||||
m_VolumeSize = m_Surface.size;
|
||||
updateNavMesh = true;
|
||||
}
|
||||
|
||||
if (updateNavMesh)
|
||||
m_Surface.UpdateNavMesh(m_Surface.navMeshData);
|
||||
}
|
||||
|
||||
static Vector3 Quantize(Vector3 v, Vector3 quant)
|
||||
{
|
||||
float x = quant.x * Mathf.Floor(v.x / quant.x);
|
||||
float y = quant.y * Mathf.Floor(v.y / quant.y);
|
||||
float z = quant.z * Mathf.Floor(v.z / quant.z);
|
||||
return new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
Vector3 QuantizedCenter()
|
||||
{
|
||||
// Quantize the center position to update only when there's a 10% change in position relative to size
|
||||
var center = trackedAgent.transform.position;
|
||||
return Quantize(center, 0.1f * m_Surface.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 115dfe7b0938447cbbf9507076f54049
|
||||
timeCreated: 1454852118
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Use physics raycast hit from mouse click to set agent destination
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(NavMeshAgent))]
|
||||
public class NavigationLoop : MonoBehaviour
|
||||
{
|
||||
NavMeshAgent m_Agent;
|
||||
public Transform[] goals = new Transform[3];
|
||||
private int m_NextGoal = 1;
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_Agent = GetComponent<NavMeshAgent>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
float distance = Vector3.Distance(m_Agent.transform.position, goals[m_NextGoal].position);
|
||||
if (distance < 0.5f)
|
||||
{
|
||||
m_NextGoal = m_NextGoal != 2 ? m_NextGoal + 1 : 0;
|
||||
}
|
||||
m_Agent.destination = goals[m_NextGoal].position;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e11f36a144a248cbacbea0c8cf7803e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Makes a transform oscillate relative to its start position
|
||||
/// </summary>
|
||||
public class Oscillator : MonoBehaviour
|
||||
{
|
||||
public float m_Amplitude = 1.0f;
|
||||
public float m_Period = 1.0f;
|
||||
public Vector3 m_Direction = Vector3.up;
|
||||
Vector3 m_StartPosition;
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_StartPosition = transform.position;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
var pos = m_StartPosition + m_Direction * m_Amplitude * Mathf.Sin(2.0f * Mathf.PI * Time.time / m_Period);
|
||||
transform.position = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c59ac8154f1b24ea7a85cab0f39a4489
|
||||
timeCreated: 1454359265
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3521e0f45779e394db0026c17503fe8a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b965d7c48dbdb594cb2678be44f7ea34
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,192 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// This class creates (if missing) or resets (after reimporting the samples) the agent types used by the samples.
|
||||
/// It is in no way necessary for using the Navigation package and is only used for the correct functioning of the samples.
|
||||
/// </summary>
|
||||
public static class NavigationSampleProjectSettingsGenerator
|
||||
{
|
||||
const string k_NavMeshSettingsPath = "ProjectSettings/NavMeshAreas.asset";
|
||||
|
||||
const float k_DefaultAgentRadius = 0.5f;
|
||||
const float k_DefaultAgentHeight = 2.0f;
|
||||
const float k_DefaultAgentClimb = 0.4f;
|
||||
const float k_DefaultAgentSlope = 45.0f;
|
||||
|
||||
const string k_HumanoidAgentTypeName = "Humanoid for Navigation Sample";
|
||||
const int k_HumanoidAgentTypeID = 1;
|
||||
const float k_HumanoidAgentClimb = 0.75f;
|
||||
|
||||
const string k_OgreAgentTypeName = "Ogre for Navigation Sample";
|
||||
const int k_OgreAgentTypeID = 2;
|
||||
const float k_OgreAgentRadius = 1.0f;
|
||||
const float k_OgreAgentSlope = 36.0f;
|
||||
|
||||
static SerializedObject s_NavMeshParameters;
|
||||
static SerializedProperty s_AgentsSettings;
|
||||
static SerializedProperty s_SettingNames;
|
||||
|
||||
public static void GenerateAllProjectSettings(NavigationSampleSettingsState settingsState)
|
||||
{
|
||||
s_NavMeshParameters = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath(k_NavMeshSettingsPath)[0]);
|
||||
|
||||
s_AgentsSettings = s_NavMeshParameters.FindProperty("m_Settings");
|
||||
s_SettingNames = s_NavMeshParameters.FindProperty("m_SettingNames");
|
||||
|
||||
var hasInitializedOnProjectLoad = settingsState.generated;
|
||||
|
||||
GenerateProjectSettings(k_HumanoidAgentTypeName, k_HumanoidAgentTypeID, CreateHumanoidAgentSettings, hasInitializedOnProjectLoad);
|
||||
GenerateProjectSettings(k_OgreAgentTypeName, k_OgreAgentTypeID, CreateOgreAgentSettings, hasInitializedOnProjectLoad);
|
||||
s_NavMeshParameters.ApplyModifiedProperties();
|
||||
settingsState.generated = true;
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
static void GenerateProjectSettings(string agentTypeName, int agentTypeID, CreateAgentSettings createAgentSettings, bool hasInitializedOnProjectLoad)
|
||||
{
|
||||
var agentProperty = GetSerializedSettingsByID(agentTypeID, out var index);
|
||||
if (index < 0)
|
||||
{
|
||||
// Create new settings
|
||||
var agentSettings = createAgentSettings();
|
||||
agentSettings.agentTypeID = agentTypeID;
|
||||
AddAgentSettings(agentSettings, agentTypeName, agentTypeID);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!HasSettingsNameAtIndex(index, agentTypeName))
|
||||
{
|
||||
// Don't update the settings
|
||||
var settingsName = s_SettingNames.GetArrayElementAtIndex(index).stringValue;
|
||||
if (!IsAgentTypeSetWithDefaultValues(index, agentTypeID))
|
||||
{
|
||||
Debug.LogWarning($"The agent type {agentTypeName} used in the Navigation Samples could not be created. The agent type {settingsName} will be used instead. {settingsName} does not have the expected values for {agentTypeName}. The expected values for {agentTypeName} are written in the README.md file of the samples. The values of agent types are updatable in the Agents tab of the AI > Navigation window.");
|
||||
}
|
||||
}
|
||||
else if (!hasInitializedOnProjectLoad && !IsAgentTypeSetWithDefaultValues(index, agentTypeID))
|
||||
{
|
||||
// Update existing settings to default values
|
||||
var radius = agentProperty.FindPropertyRelative("agentRadius").floatValue;
|
||||
var height = agentProperty.FindPropertyRelative("agentHeight").floatValue;
|
||||
var climb = agentProperty.FindPropertyRelative("agentClimb").floatValue;
|
||||
var slope = agentProperty.FindPropertyRelative("agentSlope").floatValue;
|
||||
|
||||
var tempAgentSettings = createAgentSettings();
|
||||
UpdateSettings(agentProperty, tempAgentSettings);
|
||||
NavMesh.RemoveSettings(tempAgentSettings.agentTypeID);
|
||||
|
||||
Debug.Log($"Navigation Samples reimport detected. The agent type {agentTypeName} has been reset to its default values. Its values before the reset were: Radius = {radius}, Height = {height}, Step height = {climb} and Max Slope = {slope}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsAgentTypeSetWithDefaultValues(int index, int agentTypeID)
|
||||
{
|
||||
var agentTypeSettings = s_AgentsSettings.GetArrayElementAtIndex(index);
|
||||
var radius = agentTypeSettings.FindPropertyRelative("agentRadius").floatValue;
|
||||
var height = agentTypeSettings.FindPropertyRelative("agentHeight").floatValue;
|
||||
var climb = agentTypeSettings.FindPropertyRelative("agentClimb").floatValue;
|
||||
var slope = agentTypeSettings.FindPropertyRelative("agentSlope").floatValue;
|
||||
|
||||
var result = false;
|
||||
switch (agentTypeID)
|
||||
{
|
||||
case k_HumanoidAgentTypeID:
|
||||
result = radius == k_DefaultAgentRadius && height == k_DefaultAgentHeight && climb == k_HumanoidAgentClimb && slope == k_DefaultAgentSlope;
|
||||
break;
|
||||
case k_OgreAgentTypeID:
|
||||
result = radius == k_OgreAgentRadius && height == k_DefaultAgentHeight && climb == k_DefaultAgentClimb && slope == k_OgreAgentSlope;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
delegate NavMeshBuildSettings CreateAgentSettings();
|
||||
|
||||
static NavMeshBuildSettings CreateHumanoidAgentSettings()
|
||||
{
|
||||
var humanoidAgentSettings = NavMesh.CreateSettings();
|
||||
humanoidAgentSettings.agentRadius = k_DefaultAgentRadius;
|
||||
humanoidAgentSettings.agentHeight = k_DefaultAgentHeight;
|
||||
humanoidAgentSettings.agentClimb = k_HumanoidAgentClimb;
|
||||
humanoidAgentSettings.agentSlope = k_DefaultAgentSlope;
|
||||
|
||||
return humanoidAgentSettings;
|
||||
}
|
||||
|
||||
static NavMeshBuildSettings CreateOgreAgentSettings()
|
||||
{
|
||||
var ogreAgentSettings = NavMesh.CreateSettings();
|
||||
ogreAgentSettings.agentRadius = k_OgreAgentRadius;
|
||||
ogreAgentSettings.agentHeight = k_DefaultAgentHeight;
|
||||
ogreAgentSettings.agentClimb = k_DefaultAgentClimb;
|
||||
ogreAgentSettings.agentSlope = k_OgreAgentSlope;
|
||||
|
||||
return ogreAgentSettings;
|
||||
}
|
||||
|
||||
static SerializedProperty GetSerializedSettingsByID(int agentTypeID, out int index)
|
||||
{
|
||||
index = -1;
|
||||
SerializedProperty settings = null;
|
||||
for (var i = 0; i < s_AgentsSettings.arraySize; i++)
|
||||
{
|
||||
if (s_AgentsSettings.GetArrayElementAtIndex(i).FindPropertyRelative("agentTypeID").intValue == agentTypeID)
|
||||
{
|
||||
index = i;
|
||||
settings = s_AgentsSettings.GetArrayElementAtIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
static bool HasSettingsNameAtIndex(int index, string agentTypeName)
|
||||
{
|
||||
return s_SettingNames.GetArrayElementAtIndex(index).stringValue.Equals(agentTypeName);
|
||||
}
|
||||
|
||||
static void AddAgentSettings(NavMeshBuildSettings agentSettings, string agentTypeName, int agentTypeID)
|
||||
{
|
||||
var nbNames = s_SettingNames.arraySize;
|
||||
s_SettingNames.InsertArrayElementAtIndex(nbNames);
|
||||
var newName = s_SettingNames.GetArrayElementAtIndex(nbNames);
|
||||
newName.stringValue = agentTypeName;
|
||||
|
||||
var nbAgents = s_AgentsSettings.arraySize;
|
||||
s_AgentsSettings.InsertArrayElementAtIndex(nbAgents);
|
||||
var addedAgentType = s_AgentsSettings.GetArrayElementAtIndex(nbAgents);
|
||||
|
||||
UpdateSettings(addedAgentType, agentSettings);
|
||||
|
||||
SetAgentPropertyValue(addedAgentType, "agentTypeID", agentTypeID);
|
||||
}
|
||||
|
||||
static void UpdateSettings(SerializedProperty agentToUpdate, NavMeshBuildSettings newSettings)
|
||||
{
|
||||
SetAgentPropertyValue(agentToUpdate, "agentRadius", newSettings.agentRadius);
|
||||
SetAgentPropertyValue(agentToUpdate, "agentHeight", newSettings.agentHeight);
|
||||
SetAgentPropertyValue(agentToUpdate, "agentClimb", newSettings.agentClimb);
|
||||
SetAgentPropertyValue(agentToUpdate, "agentSlope", newSettings.agentSlope);
|
||||
}
|
||||
|
||||
static void SetAgentPropertyValue(SerializedProperty agent, string propertyName, int value)
|
||||
{
|
||||
var property = agent.FindPropertyRelative(propertyName);
|
||||
property.intValue = value;
|
||||
}
|
||||
|
||||
static void SetAgentPropertyValue(SerializedProperty agent, string propertyName, float value)
|
||||
{
|
||||
var property = agent.FindPropertyRelative(propertyName);
|
||||
property.floatValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7eeb774ee02ee2e4eb6e3387169f1ada
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// This ScriptableObject is used by the NavigationSampleProjectSettingsGenerator to check whether the generation of agent types for the samples has already been done.
|
||||
/// It is in no way necessary for using the Navigation package and is only used for the correct functioning of the samples.
|
||||
/// </summary>
|
||||
public class NavigationSampleSettingsState : ScriptableObject
|
||||
{
|
||||
[SerializeField]
|
||||
bool hasGeneratedSettings;
|
||||
|
||||
public bool generated
|
||||
{
|
||||
get => hasGeneratedSettings;
|
||||
set => hasGeneratedSettings = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 299341368f0a4ce5beba0c07f7bb5bbb
|
||||
timeCreated: 1655319459
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Unity.AI.Navigation.Samples.Initialization.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1dcde1c83efa6e14e8e75ed67addeba3
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
#if UNITY_EDITOR
|
||||
using Unity.AI.Navigation.Samples.Editor;
|
||||
using UnityEditor.SceneManagement;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// The Navigation samples use a couple of custom agent types.
|
||||
/// This class calls the NavigationSampleProjectSettingsGenerator to ensure that these agent types do exist within your Unity project.
|
||||
/// It is in no way necessary for using the Navigation package and is only used for the correct functioning of the samples.
|
||||
/// </summary>
|
||||
[ExecuteAlways]
|
||||
public class NavigationSampleInitializer : MonoBehaviour
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[SerializeField]
|
||||
NavigationSampleSettingsState settingsState;
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
NavigationSampleProjectSettingsGenerator.GenerateAllProjectSettings(settingsState);
|
||||
|
||||
DestroyGameObjectAndSave(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
static void DestroyGameObjectAndSave(GameObject gameObject)
|
||||
{
|
||||
var scene = gameObject.scene;
|
||||
DestroyImmediate(gameObject);
|
||||
EditorSceneManager.SaveScene(scene);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b4f798af8320134f8549651d7ea621a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,143 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.AI;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Fill 5x5 tiles around the local position procedurally by instantiating prefabs at random positions/orientations
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(-200)]
|
||||
public class RandomInstancing : MonoBehaviour
|
||||
{
|
||||
public GameObject m_Prefab;
|
||||
public int m_PoolSize = 250;
|
||||
public int m_InstancesPerTile = 10;
|
||||
public bool m_RandomPosition = true;
|
||||
public bool m_RandomOrientation = true;
|
||||
public float m_Height;
|
||||
|
||||
public int m_BaseHash = 347652783;
|
||||
public float m_Size = 100.0f;
|
||||
|
||||
[SerializeField]
|
||||
Transform parent;
|
||||
[SerializeField]
|
||||
NavMeshAgent trackedAgent;
|
||||
|
||||
List<Transform> m_Instances = new List<Transform>();
|
||||
int m_Used;
|
||||
int m_LocX, m_LocZ;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
for (int i = 0; i < m_PoolSize; ++i)
|
||||
{
|
||||
var go = Instantiate(m_Prefab, Vector3.zero, Quaternion.identity, parent) as GameObject;
|
||||
go.SetActive(false);
|
||||
m_Instances.Add(go.transform);
|
||||
}
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_LocX = ~0;
|
||||
m_LocZ = ~0;
|
||||
UpdateInstances();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
for (int i = 0; i < m_Instances.Count; ++i)
|
||||
{
|
||||
if (m_Instances[i])
|
||||
Destroy(m_Instances[i].gameObject);
|
||||
}
|
||||
m_Instances.Clear();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (trackedAgent.remainingDistance > 0.1f)
|
||||
{
|
||||
UpdateInstances();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateInstances()
|
||||
{
|
||||
var x = (int)Mathf.Floor(transform.position.x / m_Size);
|
||||
var z = (int)Mathf.Floor(transform.position.z / m_Size);
|
||||
if (x == m_LocX && z == m_LocZ)
|
||||
return;
|
||||
|
||||
m_LocX = x;
|
||||
m_LocZ = z;
|
||||
|
||||
m_Used = 0;
|
||||
for (var i = x - 2; i <= x + 2; ++i)
|
||||
{
|
||||
for (var j = z - 2; j <= z + 2; ++j)
|
||||
{
|
||||
var count = UpdateTileInstances(i, j);
|
||||
if (count != m_InstancesPerTile)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Deactivate the remaining active elements in the pool.
|
||||
// Here we assume all active elements are contiguous and first in the list.
|
||||
for (int i = m_Used; i < m_PoolSize && m_Instances[i].gameObject.activeSelf; ++i)
|
||||
m_Instances[i].gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
int UpdateTileInstances(int i, int j)
|
||||
{
|
||||
var seed = Hash2(i, j) ^ m_BaseHash;
|
||||
var count = System.Math.Min(m_InstancesPerTile, m_PoolSize - m_Used);
|
||||
for (var end = m_Used + count; m_Used < end; ++m_Used)
|
||||
{
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
|
||||
if (m_RandomPosition)
|
||||
{
|
||||
x = Random(ref seed);
|
||||
y = Random(ref seed);
|
||||
}
|
||||
var pos = new Vector3((i + x) * m_Size, m_Height, (j + y) * m_Size);
|
||||
|
||||
if (m_RandomOrientation)
|
||||
{
|
||||
float r = 360.0f * Random(ref seed);
|
||||
m_Instances[m_Used].rotation = Quaternion.AngleAxis(r, Vector3.up);
|
||||
}
|
||||
m_Instances[m_Used].position = pos;
|
||||
m_Instances[m_Used].gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (count < m_InstancesPerTile)
|
||||
Debug.LogWarning("Pool exhausted", this);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int Hash2(int i, int j)
|
||||
{
|
||||
return (i * 73856093) ^ (j * 19349663);
|
||||
}
|
||||
|
||||
static float Random(ref int seed)
|
||||
{
|
||||
seed = (seed ^ 123459876);
|
||||
var k = seed / 127773;
|
||||
seed = 16807 * (seed - k * 127773) - 2836 * k;
|
||||
if (seed < 0)
|
||||
seed = seed + 2147483647;
|
||||
float ran0 = seed * 1.0f / 2147483647.0f;
|
||||
seed = (seed ^ 123459876);
|
||||
return ran0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0805752a20e62489680c7c8ba929bccc
|
||||
timeCreated: 1430813999
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,28 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Walk to a random position and repeat
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(NavMeshAgent))]
|
||||
public class RandomWalk : MonoBehaviour
|
||||
{
|
||||
public float m_Range = 25.0f;
|
||||
NavMeshAgent m_Agent;
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_Agent = GetComponent<NavMeshAgent>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (m_Agent.pathPending || !m_Agent.isOnNavMesh || m_Agent.remainingDistance > 0.1f)
|
||||
return;
|
||||
|
||||
m_Agent.destination = m_Range * Random.insideUnitCircle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd76b8ee2dbcf4be6998e917c65cd6ed
|
||||
timeCreated: 1431075769
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// Prefab spawner with a key input
|
||||
/// </summary>
|
||||
public class SpawnPrefabOnKeyDown : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
GameObject prefab;
|
||||
|
||||
[SerializeField]
|
||||
KeyCode keyCode;
|
||||
|
||||
[SerializeField]
|
||||
Transform spawnedPrefabsHolder;
|
||||
|
||||
Transform m_Transform;
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_Transform = transform;
|
||||
|
||||
if (spawnedPrefabsHolder == null)
|
||||
{
|
||||
spawnedPrefabsHolder = m_Transform;
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(keyCode) && prefab != null)
|
||||
Instantiate(prefab, m_Transform.position, m_Transform.rotation, spawnedPrefabsHolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c751607f01df8445c86b012985b8b152
|
||||
timeCreated: 1430998893
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user