public void Execute(int i, TransformAccess transform) { AgentBehaviors mask = AgentBehaviors.Active; if ((behaviors[i] & mask) == 0) { return; } float mass = movementConfigs[movement[i]].mass; int3 grid = GridPosition(transform.position); int3 bucket = new int3( grid.x / size.x, grid.y / size.y, grid.z / size.z ); Agents.AgentKinematics agent = agents[i]; agent.position = transform.position; agents[i] = agent; SpatialMapData data = new SpatialMapData(); data.position = transform.position; data.height = collision.height; data.radius = collision.radius; data.mass = mass; spatialMap.Add(bucket, data); }
/// <summary> /// Adds a new agent to the scene /// </summary> public NavAgent Spawn(Vector3 position) { int index = Random.Range(0, agentsToSpawn.Count); NavAgent agent = Poolable.TryGetPoolable <NavAgent>( agentsToSpawn[index].gameObject); agent.transform.localScale = Vector3.one * world.scale; agent.transform.rotation = world.transform.rotation; agent.transform.position = position; agent.gameObject.SetActive(true); NavAgentArchetype archetype = agent.configuration.archetype; int archetypeIndex = agentManager.archetypes.IndexOf(archetype); NativeArray <AgentBehaviors> behaviors = agentManager.agentBehaviors[archetypeIndex]; // set the agent's navigation behaviors AgentBehaviors flags = AgentBehaviors.Active | AgentBehaviors.Queueing | AgentBehaviors.Avoiding | AgentBehaviors.Seeking; NativeSlice <AgentBehaviors> slice = behaviors.Slice(agent.index, 1); SetAgentBehaviors activation = new SetAgentBehaviors() { flags = flags, behaviors = slice }; activation.Schedule(1, 1).Complete(); return(agent); }
public void Execute(int i) { AgentBehaviors mask = AgentBehaviors.Active; if ((behaviors[i] & mask) == 0) { return; } AgentKinematics agent = agents[i]; float3 min = agent.position + new float3(-collision.radius, -collision.radius, -collision.radius); float3 max = agent.position + new float3(collision.radius, collision.radius, collision.radius); int3 minBucket = GetSpatialBucket(min); int3 maxBucket = GetSpatialBucket(max); if (minBucket.Equals(maxBucket)) { ResolveCollisions(i, minBucket); } else { ResolveCollisions(i, minBucket, maxBucket); } }
public void Execute(int i) { AgentBehaviors mask = AgentBehaviors.Queueing; if ((behaviors[i] & mask) == 0) { return; } AgentKinematics agent = agents[i]; float3 direction = math.normalizesafe(agent.velocity, float3.zero); float3 ahead = agent.position + direction * maxQueueAhead; float3 min = ahead + new float3(-maxQueueRadius, -maxQueueRadius, -maxQueueRadius); float3 max = ahead + new float3(maxQueueRadius, maxQueueRadius, maxQueueRadius); int3 minBucket = GetSpatialBucket(min); int3 maxBucket = GetSpatialBucket(max); bool obstructed; if (minBucket.Equals(maxBucket)) { obstructed = DetectCollision(i, ahead, minBucket); } else { obstructed = DetectCollision(i, ahead, minBucket, maxBucket); } if (obstructed) { ApplyBrakeForce(i); } }
public void Execute(int i) { AgentBehaviors mask = AgentBehaviors.Active; if ((behaviors[i] & mask) == 0) { return; } AgentKinematics agent = agents[i]; int3 grid = GridPosition(agent.position); grid += new int3(0, -1, 0); byte voxel = voxels[Flatten(grid)]; if (OverAir(voxel)) { steering[i] += gravity; } if (InSolid(voxel)) { steering[i] += gravity * -0.5f; } }
public void Execute(int i) { AgentBehaviors mask = AgentBehaviors.Stopping; if ((behaviors[i] & mask) == 0) { return; } ApplyBrakeForce(i); }
/// <summary> /// Adds multiple agents randomly in the scene /// </summary> public void SpawnAgents(int count) { Vector3 position = Vector3.zero; Vector3Int grid = Vector3Int.zero; Vector2 center = new Vector2( world.size.x / 2, world.size.z / 2 ); for (int i = 0; i < count; i++) { // choose a random (x,z) position inside a circle Vector2 randomXZ = Random.insideUnitCircle; randomXZ *= world.size.x / 2; randomXZ += center; // update the agents grid position and // convert the grid position to world space grid.x = (int)randomXZ.x; grid.z = (int)randomXZ.y; grid.y = heightMap.Read(grid.x, grid.z) + 1; position = world.GridToScene(grid); // spawn the new enemy agent int index = Random.Range(0, agentsToSpawn.Count); NavAgent agent = Poolable.TryGetPoolable <NavAgent>( agentsToSpawn[index].gameObject); agent.transform.localScale = Vector3.one * world.scale; agent.transform.rotation = world.transform.rotation; agent.transform.position = position; agent.gameObject.SetActive(true); // enable the agents navigation behaviors to SEEK, QUEUE, and AVOID NavAgentArchetype archetype = agent.configuration.archetype; int archetypeIndex = agentManager.archetypes.IndexOf(archetype); NativeArray <AgentBehaviors> behaviors = agentManager.agentBehaviors[archetypeIndex]; AgentBehaviors flags = AgentBehaviors.Active | AgentBehaviors.Queueing | AgentBehaviors.Avoiding | AgentBehaviors.Seeking; NativeSlice <AgentBehaviors> slice = behaviors.Slice(agent.index, 1); SetAgentBehaviors activation = new SetAgentBehaviors() { flags = flags, behaviors = slice }; activation.Schedule(1, 1).Complete(); } }
public void Execute(int i) { AgentBehaviors mask = AgentBehaviors.Avoiding; if ((behaviors[i] & mask) == 0) { return; } AgentKinematics agent = agents[i]; float dynamicLength = math.length(agent.velocity) / avoidDistance; float3 direction = math.normalizesafe(agent.velocity, float3.zero); float3 closest = new float3(float.MaxValue, float.MaxValue, float.MaxValue); float3 ahead = agent.position + direction * dynamicLength; float3 ahead2 = agent.position + direction * dynamicLength * 0.5f; float3 min = ahead + new float3(-avoidRadius, -avoidRadius, -avoidRadius); float3 max = ahead + new float3(avoidRadius, avoidRadius, avoidRadius); float3 min2 = ahead2 + new float3(-avoidRadius, -avoidRadius, -avoidRadius); float3 max2 = ahead2 + new float3(avoidRadius, avoidRadius, avoidRadius); int3 minBucket = math.min(GetSpatialBucket(min), GetSpatialBucket(min2)); int3 maxBucket = math.max(GetSpatialBucket(max), GetSpatialBucket(max2)); bool shouldAvoid; if (minBucket.Equals(maxBucket)) { shouldAvoid = DetectObstruction(i, ahead, ahead2, minBucket, ref closest); } else { shouldAvoid = DetectObstruction(i, ahead, ahead2, minBucket, maxBucket, ref closest); } if (shouldAvoid) { ApplyAvoidanceForce(i, ahead, closest); } }
/// <summary> /// Removes an agent from the scene /// </summary> public void Remove(Enemy enemy) { NavAgent agent = enemy.GetComponent <NavAgent>(); Poolable.TryPool(agent.gameObject); // set the agent's navigation behaviors to NONE NavAgentArchetype archetype = agent.configuration.archetype; int archetypeIndex = agentManager.archetypes.IndexOf(archetype); NativeArray <AgentBehaviors> behaviors = agentManager.agentBehaviors[archetypeIndex]; AgentBehaviors flags = AgentBehaviors.None; NativeSlice <AgentBehaviors> slice = behaviors.Slice(agent.index, 1); SetAgentBehaviors activation = new SetAgentBehaviors() { flags = flags, behaviors = slice }; activation.Schedule(1, 1).Complete(); }
public void Execute(int i) { AgentBehaviors mask = AgentBehaviors.Seeking; if ((behaviors[i] & mask) == 0) { return; } AgentKinematics agent = agents[i]; int3 grid = GridPosition(agent.position); grid += new int3(0, -1, 0); if (OutOfBounds(grid)) { steering[i] = float3.zero; return; } int fieldIndex = Flatten(grid); byte directionIndex = flowField[fieldIndex]; if (directionIndex == 0) // no direction { steering[i] = float3.zero; return; } int3 flowDirection = flowDirections[directionIndex]; int3 nextGrid = grid + flowDirection + new int3(0, 1, 0); float3 nextPosition = ScenePosition(nextGrid); float3 desired = nextPosition - agent.position; desired = math.normalizesafe(desired, float3.zero); desired *= movementTypes[agentMovement[i]].topSpeed; steering[i] = desired - agent.velocity; }
public void Execute(int i, TransformAccess transform) { AgentBehaviors mask = AgentBehaviors.Active; if ((behaviors[i] & mask) == 0) { return; } float3 up = new float3(0, 1, 0); float3 position = transform.position; quaternion rotation = transform.rotation; AgentMovement movement = movementTypes[agentMovement[i]]; AgentKinematics agent = agents[i]; steering[i] = Clamp(steering[i], maxForce); steering[i] = steering[i] / movement.mass; agent.velocity = Clamp(agent.velocity + steering[i], agent.maxSpeed); steering[i] = float3.zero; // reset steering forces for next frame agents[i] = agent; // update the kinematics for the next frame float3 nextPosition = agent.position + agent.velocity * deltaTime; int3 nextGrid = GridPosition(nextPosition); if (OutOfBounds(nextGrid)) { return; } transform.position = nextPosition; if (agent.velocity.Equals(float3.zero)) { return; } quaternion look = quaternion.LookRotation(agent.velocity, up); transform.rotation = math.slerp(rotation, look, movement.turnSpeed * deltaTime); }
public void AvoidsNearbyAgents() { float3 position1 = float3.zero; float3 position2 = new float3(0f, 1f, 0f); float3 max = new float3(float.MaxValue, float.MaxValue, float.MaxValue); NativeMultiHashMap <int3, SpatialMapData> spatialMap = new NativeMultiHashMap <int3, SpatialMapData>(1, Allocator.Persistent); spatialMap.Add(int3.zero, new SpatialMapData() { position = position1 }); spatialMap.Add(int3.zero, new SpatialMapData() { position = position2 }); NativeArray <AgentKinematics> agents = new NativeArray <AgentKinematics>(2, Allocator.Persistent); agents[0] = new AgentKinematics() { position = position1, velocity = new float3(0, 0, 0) }; agents[1] = new AgentKinematics() { position = position2, velocity = new float3(0, 1, 0) }; NativeArray <float3> steering = new NativeArray <float3>(2, Allocator.Persistent); NativeArray <AgentBehaviors> active = new NativeArray <AgentBehaviors>(2, Allocator.Persistent); AgentBehaviors flags = AgentBehaviors.Avoiding; for (int i = 0; i < 2; i++) { active[i] = flags; } AgentWorld world = new AgentWorld() { scale = 1f, offset = float3.zero, center = new float3(0.5f, 0.5f, 0.5f), rotation = quaternion.identity, }; AvoidCollisionBehavior job = new AvoidCollisionBehavior() { avoidDistance = 1f, avoidRadius = 1f, avoidForce = 1f, maxDepth = 100, world = world, size = new int3(1, 1, 1), spatialMap = spatialMap, steering = steering, behaviors = active, agents = agents, }; job.Schedule(2, 1).Complete(); Assert.AreEqual(new float3(0, -1, 0), steering[0]); Assert.AreEqual(new float3(0, 0, 0), steering[1]); spatialMap.Dispose(); steering.Dispose(); agents.Dispose(); active.Dispose(); }