/// <summary> /// Calculates the required force to separate the two agents /// </summary> public void ApplyCollisionForce(int i, SpatialMapData target) { // calculate the distance bewteen the two agents float3 direction = agents[i].position - target.position; direction.y = 0; // clamp the y-axis to create a 2D force // exit if the agents are within the minimum distance // this helps prevent excessive collision forces float distance = math.length(direction); if (distance <= minDistance) { return; } // calculate the mass difference between the two agents float mass = movementConfigs[movement[i]].mass; float massRatio = target.mass / mass; // calcuate the collision force for this agent and skip // if it does not exceed the minForce, creating a deadband float combinedRadius = collision.radius + target.radius; float penetration = combinedRadius / distance; float forceScale = penetration * massRatio; if (forceScale <= minForce) { return; } // apply the collision to this agents steering force direction = math.normalizesafe(direction, float3.zero); steering[i] += direction * forceScale; }
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> /// Checks if there is a collision between two agents /// using their collision radius and height /// </summary> public bool Collision(AgentKinematics self, SpatialMapData target) { // skip if the target agent is the same as the source agent if (self.position.Equals(target.position)) { return(false); } // find the distance between the two agents // clamp y-axis to test 2D circle intersection float3 delta = self.position - target.position; float deltaY = delta.y; delta.y = 0; // use the combined radius of the two agents to // test if their collision radius intersect float distance = math.length(delta); float radius = collision.radius + target.radius; bool intersectCircle = distance <= radius; // compare the two agent's height and offset for collisions // use delta Y to test that the agents are colliding with each other bool intersectHeight; if (deltaY >= 0) // target is above the agent { intersectHeight = deltaY - collision.height < 0; } else // target is below the agent { intersectHeight = -deltaY - target.height < 0; } // agents must be intersecting the 2D circle // and height to be considered a collision return(intersectCircle && intersectHeight); }