public static unsafe bool ColliderCastAllTargets(float3 rayFrom, float3 rayTo, quaternion rotation, CollisionWorld collisionWorld, PhysicsCollider collider, ref NativeList <Entity> allHitEntities) { ColliderCastInput input = new ColliderCastInput() { Collider = (Collider *)collider.Value.GetUnsafePtr(), Orientation = rotation, Start = rayFrom, End = rayTo }; NativeList <ColliderCastHit> colliderCastHits = new NativeList <ColliderCastHit>(Allocator.Temp); if (collisionWorld.CastCollider(input, ref colliderCastHits)) { //Extract entities for (int i = 0; i < colliderCastHits.Length; ++i) { allHitEntities.Add(colliderCastHits[i].Entity); } return(true); } return(false); }
public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var chunkTranslations = chunk.GetNativeArray(TranslationType); var chunkFighterSearchInputBuffers = chunk.GetBufferAccessor(FighterSearchInputBufferType); var chunkFighterSearchHitDistanceBuffers = chunk.GetBufferAccessor(FighterSearchHitDistanceBufferType); for (var i = 0; i < chunk.Count; ++i) { DynamicBuffer <FighterSearchInputBuffer> input_buf = chunkFighterSearchInputBuffers[i]; DynamicBuffer <FighterSearchHitDistanceBuffer> hit_buf = chunkFighterSearchHitDistanceBuffers[i]; for (var j = 0; j < input_buf.Length; ++j) { ColliderCastHit hit; bool hitted = world.CastCollider(input_buf[j].Value, out hit); if (hitted) { hit_buf[j] = new FighterSearchHitDistanceBuffer { Value = math.length(hit.Position - chunkTranslations[i].Value), }; } else { hit_buf[j] = new FighterSearchHitDistanceBuffer { Value = float.MaxValue, }; } } ; } }
public static unsafe bool ColliderCast(float3 rayFrom, float3 rayTo, quaternion rotation, CollisionWorld collisionWorld, PhysicsCollider collider) { ColliderCastInput input = new ColliderCastInput() { Collider = (Collider *)collider.Value.GetUnsafePtr(), Orientation = rotation, Start = rayFrom, End = rayTo }; return(collisionWorld.CastCollider(input)); }
public static unsafe bool BoxCast(float3 rayFrom, float3 rayTo, CollisionWorld collisionWorld, BoxGeometry boxGeometry, CollisionFilter collisionFilter) { BlobAssetReference <Collider> boxCollider = BoxCollider.Create(boxGeometry, collisionFilter); ColliderCastInput input = new ColliderCastInput() { Collider = (Collider *)boxCollider.GetUnsafePtr(), Orientation = quaternion.identity, Start = rayFrom, End = rayTo }; return(collisionWorld.CastCollider(input)); }
public unsafe static void SphereCastAll(CollisionWorld world, float radius, uint mask, float3 origin, float3 direction, NativeList <ColliderCastHit> results) { var sphereCollider = Unity.Physics.SphereCollider.Create(float3.zero, radius, new CollisionFilter() { CategoryBits = mask, MaskBits = mask, GroupIndex = (int)mask }); ColliderCastInput input = new ColliderCastInput() { Position = origin, Orientation = quaternion.identity, Direction = direction, Collider = (Collider *)sphereCollider.GetUnsafePtr() }; world.CastCollider(input, ref results); }
/// <summary> /// Performs a collider cast along the specified ray and returns all resulting <see cref="ColliderCastHit"/>s.<para/> /// /// The caller must dispose of the returned list. /// </summary> /// <param name="collider"></param> /// <param name="from"></param> /// <param name="to"></param> /// <param name="collisionWorld"></param> /// <param name="ignore">Will ignore this entity if it was hit. Useful to prevent returning hits from the caster.</param> /// <returns></returns> public unsafe static NativeList <ColliderCastHit> ColliderCastAll(PhysicsCollider collider, float3 from, float3 to, ref CollisionWorld collisionWorld, Entity ignore, Allocator allocator = Allocator.TempJob) { ColliderCastInput input = new ColliderCastInput() { Collider = collider.ColliderPtr, Start = from, End = to }; NativeList <ColliderCastHit> allHits = new NativeList <ColliderCastHit>(allocator); if (collisionWorld.CastCollider(input, ref allHits)) { TrimByEntity(ref allHits, ignore); } return(allHits); }
public unsafe static NativeArray <Entity> GetNearbyObjects(Entity e, float3 translation, quaternion rotation, PhysicsCollider physicsCollider, BuildPhysicsWorld physicsWorldSystem) { CollisionWorld world = physicsWorldSystem.PhysicsWorld.CollisionWorld;; NativeArray <Entity> context; var filter = new CollisionFilter() { BelongsTo = ~0u, CollidesWith = ~0u, // all 1s, so all layers, collide with everything GroupIndex = 0 }; SphereGeometry sphereGeometry = new SphereGeometry() { Center = float3.zero, Radius = 3f }; BlobAssetReference <Collider> sphereCollider = SphereCollider.Create(sphereGeometry, filter); NativeList <ColliderCastHit> colliderHit = new NativeList <ColliderCastHit>(); ColliderCastInput input = new ColliderCastInput() { Collider = (Collider *)sphereCollider.GetUnsafePtr(), Orientation = quaternion.identity, Start = translation, End = translation }; if (world.CastCollider(input, ref colliderHit)) { int compteur = 0; context = new NativeArray <Entity>(colliderHit.Length, Allocator.Temp); foreach (var collider in colliderHit) { context[compteur] = collider.Entity; compteur++; } Debug.Log(context.Length); } else { context = new NativeArray <Entity>(0, Allocator.Temp); Debug.Log("inhere"); } return(context); }
public static unsafe Entity ColliderCast(float3 rayFrom, float3 rayTo, quaternion rotation, CollisionWorld collisionWorld, PhysicsCollider collider, PhysicsWorld physicsWorld) { ColliderCastInput input = new ColliderCastInput() { Collider = (Collider *)collider.Value.GetUnsafePtr(), Orientation = rotation, Start = rayFrom, End = rayTo }; ColliderCastHit hit = new ColliderCastHit(); if (collisionWorld.CastCollider(input, out hit)) { return(physicsWorld.Bodies[hit.RigidBodyIndex].Entity); } return(Entity.Null); }
unsafe public void Execute(int index) { var center = math.lerp(upperRightPosition, lowerLeftPosition, 0.5f); var size = new float3(startPosition.x - endPosition.x, startPosition.y - endPosition.y, 1); var filter = new CollisionFilter() { BelongsTo = ~0u, CollidesWith = ~0u, // all 1s, so all layers, collide with everything GroupIndex = 0 }; BoxGeometry boxGeometry = new BoxGeometry() { Center = new float3(0, 0, 0) - new float3(startPosition.x - endPosition.x, startPosition.y - endPosition.y, 1) / 2, Size = (size * math.sign(size)) + new float3(1, 1, 1), Orientation = quaternion.identity, BevelRadius = 0, }; BlobAssetReference <Unity.Physics.Collider> boxColliser = Unity.Physics.BoxCollider.Create(boxGeometry, filter); ColliderCastInput input = new ColliderCastInput() { Collider = (Unity.Physics.Collider *)boxColliser.GetUnsafePtr(), Orientation = quaternion.identity, Start = startPosition, End = startPosition }; NativeList <ColliderCastHit> allHits = new NativeList <ColliderCastHit> (500, Allocator.Temp); bool haveHit = collisionWorld.CastCollider(input, ref allHits); if (haveHit) { for (int i = 0; i < allHits.Length; i++) { var hit = allHits[i]; Entity e = physicsWorld.Bodies[hit.RigidBodyIndex].Entity; entityCommandBuffer.AddComponent(index, e, new SelectedTag()); } } }
public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { BufferAccessor <ContactInfos> chunkContactInfosBuffers = chunk.GetBufferAccessor(ContactInfos); var colliders = chunk.GetNativeArray(Collider); var colliderLocalToWorlds = chunk.GetNativeArray(LocalToWorld); for (var i = 0; i < chunk.Count; i++) { DynamicBuffer <ContactInfos> contactInfosBuffer = chunkContactInfosBuffers[i]; contactInfosBuffer.Clear(); float3 position = colliderLocalToWorlds[i].Position; ColliderCastInput colliderCastInput = new ColliderCastInput() { Start = position, End = position, Collider = colliders[i].ColliderPtr }; NativeList <ColliderCastHit> hits = new NativeList <ColliderCastHit>(Allocator.Temp); if (CollisionWorld.CastCollider(colliderCastInput, ref hits)) { foreach (var hit in hits) { if (Bodies[hit.RigidBodyIndex].Collider.GetUnsafePtr() == colliderCastInput.Collider) { continue; } contactInfosBuffer.Add(new ContactInfos() { Entity = Bodies[hit.RigidBodyIndex].Entity, Contact = hit }); } } hits.Dispose(); } }
protected unsafe override void OnUpdate() { float time = Time.DeltaTime; float dirForward = Input.GetAxis("Vertical"); float dirAngle = Input.GetAxis("Horizontal"); CollisionWorld world = physicsWorldSystem.PhysicsWorld.CollisionWorld; Entities.ForEach((Entity e, ref PhysicsVelocity physicsVelocity, ref Rotation rotation, ref Translation translation, ref PhysicsCollider physicsCollider) => { var filter = new CollisionFilter() { BelongsTo = ~0u, CollidesWith = ~0u, // all 1s, so all layers, collide with everything GroupIndex = 0 }; SphereGeometry sphereGeometry = new SphereGeometry() { Center = translation.Value, Radius = 10f }; BlobAssetReference <Collider> sphereCollider = SphereCollider.Create(sphereGeometry, filter); NativeList <ColliderCastHit> colliderHit = new NativeList <ColliderCastHit>(Allocator.Temp); ColliderCastInput input = new ColliderCastInput() { Collider = (Collider *)sphereCollider.GetUnsafePtr(), Orientation = quaternion.identity, Start = translation.Value, End = translation.Value }; world.CastCollider(input, ref colliderHit); //for (int i = 0; i < colliderHit.Length; i++) //{ //Debug.Log(colliderHit[i].Entity + " / " + e.Index); //} //Debug.Log(colliderHit.Length); colliderHit.Dispose(); //NativeArray<Entity> context = GetNearbyObjects(e, translation.Value, rotation.Value, physicsCollider, test); //context.Dispose(); }).ScheduleParallel(); }
public unsafe static ColliderCastHit SphereCast(CollisionWorld world, float radius, uint mask, float3 origin, float3 direction) { var sphereCollider = Unity.Physics.SphereCollider.Create(float3.zero, radius, new CollisionFilter() { CategoryBits = mask, MaskBits = mask, GroupIndex = (int)mask }); ColliderCastInput input = new ColliderCastInput() { Position = origin, Orientation = quaternion.identity, Direction = direction, Collider = (Collider *)sphereCollider.GetUnsafePtr() }; ColliderCastHit hit = new ColliderCastHit() { RigidBodyIndex = -1 }; world.CastCollider(input, out hit); return(hit); }
public unsafe void Execute(int index) { Results.BeginForEachIndex(index); int numRows = (Request.ImageResolution + Results.ForEachCount - 1) / Results.ForEachCount; const float sphereRadius = 0.005f; BlobAssetReference <Collider> sphere; if (Request.CastSphere) { sphere = SphereCollider.Create(float3.zero, sphereRadius, Request.CollisionFilter); } for (int yCoord = index * numRows; yCoord < math.min(Request.ImageResolution, (index + 1) * numRows); yCoord++) { for (int xCoord = 0; xCoord < Request.ImageResolution; xCoord++) { float xFrac = 2.0f * ((xCoord / (float)Request.ImageResolution) - 0.5f); float yFrac = 2.0f * ((yCoord / (float)Request.ImageResolution) - 0.5f); float3 targetImagePlane = Request.ImageCenter + Request.Up * Request.PlaneHalfExtents * yFrac + Request.Right * Request.PlaneHalfExtents * xFrac; float3 rayDir = Request.RayLength * (Request.PinHole - targetImagePlane); RaycastHit hit; bool hasHit; if (Request.CastSphere) { var input = new ColliderCastInput { Collider = (Collider *)sphere.GetUnsafePtr(), Orientation = quaternion.identity, Start = Request.PinHole, End = Request.PinHole + rayDir }; hasHit = World.CastCollider(input, out ColliderCastHit colliderHit); hit = new RaycastHit { Fraction = colliderHit.Fraction, Position = colliderHit.Position, SurfaceNormal = colliderHit.SurfaceNormal, RigidBodyIndex = colliderHit.RigidBodyIndex, ColliderKey = colliderHit.ColliderKey }; } else { var rayCastInput = new RaycastInput { Start = Request.PinHole, End = Request.PinHole + rayDir, Filter = Request.CollisionFilter }; hasHit = World.CastRay(rayCastInput, out hit); } Color hitColor = Color.black; if (hasHit) { if (hit.RigidBodyIndex < NumDynamicBodies) { hitColor = Color.yellow; } else { hitColor = Color.grey; } // Lighten alternate keys if (Request.AlternateKeys && !hit.ColliderKey.Equals(ColliderKey.Empty)) { Collider *collider = World.Bodies[hit.RigidBodyIndex].Collider; hit.ColliderKey.PopSubKey(collider->NumColliderKeyBits, out uint key); if (key % 2 == 0) { Color.RGBToHSV(hitColor, out float h, out float s, out float v); hitColor = Color.HSVToRGB(h, s, v + 0.25f); } } if (Request.Shadows) { float3 hitPos = Request.PinHole + rayDir * hit.Fraction + hit.SurfaceNormal * 0.001f; bool shadowHit = false; if (Request.CastSphere) { var start = hitPos + hit.SurfaceNormal * sphereRadius; var input = new ColliderCastInput { Collider = (Collider *)sphere.GetUnsafePtr(), Orientation = quaternion.identity, Start = start, End = start + (Request.LightDir * Request.RayLength), }; ColliderCastHit colliderHit; shadowHit = World.CastCollider(input, out colliderHit); } else { var rayCastInput = new RaycastInput { Start = hitPos, End = hitPos + (Request.LightDir * Request.RayLength), Filter = Request.CollisionFilter }; RaycastHit shadowOutput; shadowHit = World.CastRay(rayCastInput, out shadowOutput); } if (shadowHit) { hitColor *= 0.4f; } } } float lighting = math.min(1.0f, math.max(Request.AmbientLight, Vector3.Dot(hit.SurfaceNormal, Request.LightDir))); Results.Write(xCoord); Results.Write(yCoord); Results.Write(hitColor * lighting); } } Results.EndForEachIndex(); }
/// <summary> /// Gets the final position of a character attempting to move from a starting /// location with a given movement. The goal of this is to move the character /// but have the character 'bounce' off of objects at angles that are /// are along the plane perpendicular to the normal of the surface hit. /// This will cancel motion through the object and instead deflect it /// into another direction giving the effect of sliding along objects /// while the character's momentum is absorbed into the wall. /// </summary> /// <param name="commandBuffer">Command buffer for adding push events to objects</param> /// <param name="jobIndex">Index of this job for command buffer use</param> /// <param name="collisionWorld">World for checking collisions and other colliable objects</param> /// <param name="start">Starting location</param> /// <param name="movement">Intended direction of movement</param> /// <param name="collider">Collider controlling the character</param> /// <param name="entityIndex">Index of this entity</param> /// <param name="rotation">Current character rotation</param> /// <param name="physicsMassAccessor">Accessor to physics mass components</param> /// <param name="anglePower">Power to raise decay of movement due to /// changes in angle between intended movement and angle of surface. /// Will be angleFactor= 1 / (1 + normAngle) where normAngle is a normalized value /// between 0-1 where 1 is max angle (90 deg) and 0 is min angle (0 degrees). /// AnglePower is the power to which the angle factor is raised /// for a sharper decline. Value of zero negates this property. /// <param name="maxBounces">Maximum number of bounces when moving. /// After this has been exceeded the bouncing will stop. By default /// this is one assuming that each move is fairly small this should approximate /// normal movement.</param> /// <param name="pushPower">Multiplier for power when pushing on an object. /// Larger values mean more pushing.</param> /// <param name="pushDecay">How much does the current push decay the remaining /// movement by. Values between [0, 1]. A zero would mean all energy is lost /// when pushing, 1 means no momentum is lost by pushing. A value of 0.5 /// would mean half of the energy is lost</param> /// <param name="epsilon">Epsilon parameter for pushing away from objects to avoid colliding /// with static objects. Should be some small float value that can be /// tuned for how much to push away while not allowing being shoved into objects.</param> /// <returns>The final location of the character.</returns> public static unsafe float3 ProjectValidMovement( EntityCommandBuffer.ParallelWriter commandBuffer, int jobIndex, CollisionWorld collisionWorld, float3 start, float3 movement, PhysicsCollider collider, int entityIndex, quaternion rotation, ComponentDataFromEntity <PhysicsMass> physicsMassGetter, float anglePower = 2, int maxBounces = 1, float pushPower = 25, float pushDecay = 0, float epsilon = 0.001f) { float3 from = start; // Starting location of movement float3 remaining = movement; // Remaining momentum int bounces = 0; // current number of bounces // Continue computing while there is momentum and bounces remaining while (math.length(remaining) > epsilon && bounces <= maxBounces) { // Get the target location given the momentum float3 target = from + remaining; // Do a cast of the collider to see if an object is hit during this // movement action var input = new ColliderCastInput() { Start = from, End = target, Collider = collider.ColliderPtr, Orientation = rotation }; SelfFilteringClosestHitCollector <ColliderCastHit> hitCollector = new SelfFilteringClosestHitCollector <ColliderCastHit>(entityIndex, 1.0f, collisionWorld); bool collisionOcurred = collisionWorld.CastCollider(input, ref hitCollector); if (!collisionOcurred && hitCollector.NumHits == 0) { // If there is no hit, target can be returned as final position return(target); } Unity.Physics.ColliderCastHit hit = hitCollector.ClosestHit; // Set the fraction of remaining movement (minus some small value) from = from + remaining * hit.Fraction; // Push slightly along normal to stop from getting caught in walls from = from + hit.SurfaceNormal * epsilon; // Apply some force to the object hit if it is moveable, Apply force on entity hit bool isKinematic = physicsMassGetter.HasComponent(hit.Entity) && IsKinematic(physicsMassGetter[hit.Entity]); if (hit.RigidBodyIndex < collisionWorld.NumDynamicBodies && !isKinematic) { commandBuffer.AddBuffer <PushForce>(jobIndex, hit.Entity); commandBuffer.AppendToBuffer(jobIndex, hit.Entity, new PushForce() { force = movement * pushPower, point = hit.Position }); // If pushing something, reduce remaining force significantly remaining *= pushDecay; } // Get angle between surface normal and remaining movement float angleBetween = math.length(math.dot(hit.SurfaceNormal, remaining)) / math.length(remaining); // Normalize angle between to be between 0 and 1 angleBetween = math.min(KCCUtils.MaxAngleShoveRadians, math.abs(angleBetween)); float normalizedAngle = angleBetween / KCCUtils.MaxAngleShoveRadians; // Create angle factor using 1 / (1 + normalizedAngle) float angleFactor = 1.0f / (1.0f + normalizedAngle); // If the character hit something // Reduce the momentum by the remaining movement that ocurred remaining *= (1 - hit.Fraction) * math.pow(angleFactor, anglePower); // Rotate the remaining remaining movement to be projected along the plane // of the surface hit (emulate pushing against the object) // A is our vector and B is normal of plane // A || B = B × (A×B / |B|) / |B| // From http://www.euclideanspace.com/maths/geometry/elements/plane/lineOnPlane/index.htm float3 planeNormal = hit.SurfaceNormal; float momentumLeft = math.length(remaining); remaining = math.cross(planeNormal, math.cross(remaining, planeNormal) / math.length(planeNormal)) / math.length(planeNormal); remaining = math.normalizesafe(remaining) * momentumLeft; // Track number of times the character has bounced bounces++; } return(from); }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { _collisionWorld.CastCollider(_colliderInput, ref _allHits); }
public unsafe void Execute(int index) { World.CastCollider(Inputs[index], out var hit); Results[index] = hit; }