// I might not want to get the closest enemy, but a specific enemy. // might use entity.id + entity.version of an entity and get position of entity // if current target is destroyed, maybe seach for new target or destroy bullet // add another option for auto mode // start with auto and maybe can focus on specifics later public void CheckForObstacle(int index) { CollisionFilter obstacleFilter = new CollisionFilter() { BelongsTo = ~0u, CollidesWith = 16u + groupIndex, GroupIndex = 0 }; PointDistanceInput obstacePointDistanceInput = new PointDistanceInput { Position = cellSeparation[index], MaxDistance = boidsData[index].obstacleAversionDistance, Filter = obstacleFilter }; if (physicsWorld.CalculateDistance(obstacePointDistanceInput, out DistanceHit obstaceHit)) { cellObstaclePositions[index] = obstaceHit.Position; cellObstacleDistance[index] = obstaceHit.Distance; if (obstaceHit.Distance < settings.boidRadius) { Entity targetEntity = physicsWorld.CollisionWorld.Bodies[obstaceHit.RigidBodyIndex].Entity; var hash = (int)math.hash(new int2(targetEntity.Index, targetEntity.Version)); damageDict.Add(hash, 1); killTrigger[index] = 1; } } else { cellObstacleDistance[index] = boidsData[index].obstacleAversionDistance + 1; } }
public unsafe void PhysicsBodyCalculateDistancePointTest() { var geometry = new BoxGeometry { Size = new float2(1f), }; using (var collider = PhysicsBoxCollider.Create(geometry)) { var physicsBody = new PhysicsBody(collider); var queryInput = new PointDistanceInput { Position = new float2(-10f), Filter = CollisionFilter.Default }; var closestHit = new DistanceHit(); var allHits = new NativeList <DistanceHit>(Allocator.Temp); // OK case : with enough max distance queryInput.MaxDistance = 10000.0f; Assert.IsTrue(physicsBody.CalculateDistance(queryInput)); Assert.IsTrue(physicsBody.CalculateDistance(queryInput, out closestHit)); Assert.IsTrue(physicsBody.CalculateDistance(queryInput, ref allHits)); // Fail case : not enough max distance queryInput.MaxDistance = 1; Assert.IsFalse(physicsBody.CalculateDistance(queryInput)); Assert.IsFalse(physicsBody.CalculateDistance(queryInput, out closestHit)); Assert.IsFalse(physicsBody.CalculateDistance(queryInput, ref allHits)); allHits.Dispose(); } }
protected override JobHandle OnUpdate(JobHandle inputDeps) { PhysicsWorld physicsWorld = buildPhysicsWorld.PhysicsWorld; inputDeps = JobHandle.CombineDependencies(inputDeps, buildPhysicsWorld.FinalJobHandle); inputDeps = JobHandle.CombineDependencies(inputDeps, stepPhysicsWorld.FinalJobHandle); var jobHandle = Entities.ForEach((ref DynamicBuffer <EntityBufferElement> adjacentEntities, in Translation position, in BugComponent bug) => { NativeList <DistanceHit> distanceHits = new NativeList <DistanceHit>(Allocator.Temp); var pointDistanceInput = new PointDistanceInput { Position = position.Value, MaxDistance = bug.Radius, Filter = LayerFilter(Layer.Bug, Layer.Obstacle) }; physicsWorld.CalculateDistance(pointDistanceInput, ref distanceHits); adjacentEntities.Clear(); var adjacent = adjacentEntities.Reinterpret <Entity>(); for (int i = 0; i < distanceHits.Length; i++) { adjacent.Add(distanceHits[i].Entity); } distanceHits.Dispose(); })
public static bool OverlapSphereCustom <T, C>(ref T target, float3 position, sfloat radius, ref C collector, CollisionFilter filter, QueryInteraction queryInteraction = QueryInteraction.Default) where T : struct, ICollidable where C : struct, ICollector <DistanceHit> { PointDistanceInput input = new PointDistanceInput { Filter = filter, MaxDistance = radius, Position = position }; if (queryInteraction == QueryInteraction.Default) { return(target.CalculateDistance(input, ref collector)); } else { unsafe { var interactionCollector = new QueryInteractionCollector <DistanceHit, C> { Collector = collector }; bool returnValue = target.CalculateDistance(input, ref interactionCollector); collector = interactionCollector.Collector; return(returnValue); } } }
protected unsafe override JobHandle OnUpdate(JobHandle inputDependencies) { var job = new DamageAreaHitDetectionSystemJob(); job.DamageEntities = DamageAreaQuery.ToEntityArray(Allocator.TempJob); job.Translations = DamageAreaQuery.ToComponentDataArray <Translation>(Allocator.TempJob); job.DamageAreas = DamageAreaQuery.ToComponentDataArray <DamageArea>(Allocator.TempJob); job.PhysicsWorld = _physicsWorld.PhysicsWorld; job.DamageAreasFromEntity = GetComponentDataFromEntity <DamageArea>(); job.HealthsFromEntity = GetComponentDataFromEntity <Health>(); job.DistanceHits = new NativeArray <DistanceHit>(128, Allocator.TempJob); PointDistanceInput = new PointDistanceInput { Position = float3.zero, MaxDistance = 50 }; job.pointDistanceInput = PointDistanceInput; inputDependencies = job.Schedule(inputDependencies); inputDependencies.Complete(); return(inputDependencies); }
public unsafe void RigidBodyCalculateDistancePointTest() { Physics.RigidBody rigidbody = Unity.Physics.RigidBody.Zero; const float size = 1.0f; const float convexRadius = 0.0f; var queryPos = new float3(-10, -10, -10); rigidbody.Collider = (Collider *)BoxCollider.Create(float3.zero, quaternion.identity, new float3(size), convexRadius).GetUnsafePtr(); var pointDistanceInput = new PointDistanceInput(); pointDistanceInput.Position = queryPos; pointDistanceInput.Filter = CollisionFilter.Default; var closestHit = new DistanceHit(); var allHits = new NativeList <DistanceHit>(Allocator.Temp); // OK case : with enough max distance pointDistanceInput.MaxDistance = 10000.0f; Assert.IsTrue(rigidbody.CalculateDistance(pointDistanceInput)); Assert.IsTrue(rigidbody.CalculateDistance(pointDistanceInput, out closestHit)); Assert.IsTrue(rigidbody.CalculateDistance(pointDistanceInput, ref allHits)); // Fail case : not enough max distance pointDistanceInput.MaxDistance = 1; Assert.IsFalse(rigidbody.CalculateDistance(pointDistanceInput)); Assert.IsFalse(rigidbody.CalculateDistance(pointDistanceInput, out closestHit)); Assert.IsFalse(rigidbody.CalculateDistance(pointDistanceInput, ref allHits)); }
static unsafe void CheckRaycastHit(ref Physics.PhysicsWorld world, RaycastInput input, RaycastHit hit, string failureMessage) { // Fetch the leaf collider ChildCollider leaf; { Physics.RigidBody body = world.Bodies[hit.RigidBodyIndex]; Collider.GetLeafCollider(body.Collider, body.WorldFromBody, hit.ColliderKey, out leaf); } // Check that the hit position matches the fraction float3 hitPosition = input.Ray.Origin + input.Ray.Direction * hit.Fraction; Assert.Less(math.length(hitPosition - hit.Position), tolerance, failureMessage + ": inconsistent fraction and position"); // Query the hit position and check that it's on the surface of the shape PointDistanceInput pointInput = new PointDistanceInput { Position = math.transform(math.inverse(leaf.TransformFromChild), hit.Position), MaxDistance = float.MaxValue }; DistanceHit distanceHit; leaf.Collider->CalculateDistance(pointInput, out distanceHit); if (((ConvexCollider *)leaf.Collider)->ConvexHull.ConvexRadius > 0.0f) { // Convex raycast approximates radius, so it's possible that the hit position is not exactly on the shape, but must at least be outside Assert.Greater(distanceHit.Distance, -tolerance, failureMessage); } else { Assert.AreEqual(distanceHit.Distance, 0.0f, tolerance, failureMessage); } }
private JobHandle UpdateWithCollider2ColliderQuery(JobHandle inputDeps) { var physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem <BuildPhysicsWorld>(); var collisionWorld = physicsWorldSystem.PhysicsWorld.CollisionWorld; // this is probably redundant but just for safety lets include all previous physics systems inputDeps = JobHandle.CombineDependencies(inputDeps, finalPhysicsSystem.FinalJobHandle); inputDeps = JobHandle.CombineDependencies(inputDeps, buildPhysicsSystem.FinalJobHandle); inputDeps = JobHandle.CombineDependencies(inputDeps, stepPhysicsSystem.FinalJobHandle); inputDeps = Entities.ForEach((Entity entity, ref EntitiesAroundCountCmp around, in Translation translation, in PhysicsCollider collider) => { around.count = 0; float3 offset = new float3(around.range, 1, around.range); OverlapAabbInput input = new OverlapAabbInput() { Aabb = new Aabb() { Min = translation.Value - offset, Max = translation.Value + offset, }, Filter = CollisionFilter.Default }; NativeList <int> bodyIndices = new NativeList <int>(Allocator.Temp); // OverlapAabb is really nice and fast, all expected colliders are returned if (collisionWorld.OverlapAabb(input, ref bodyIndices)) { for (int i = 0; i < bodyIndices.Length; ++i) { var body = collisionWorld.Bodies[bodyIndices[i]]; // why this returns true for colliders in AABB instead of actual distance? var colliderDistanceInput = new ColliderDistanceInput() { Collider = collider.ColliderPtr, Transform = RigidTransform.identity, MaxDistance = around.range }; // why this always returns false? var pointDistanceInput = new PointDistanceInput() { Filter = CollisionFilter.Default, MaxDistance = around.range, Position = translation.Value }; if (body.CalculateDistance(pointDistanceInput)) { ++around.count; } } } bodyIndices.Dispose(); })
public bool CalculateDistance <T>(PointDistanceInput input, ref T collector) where T : struct, ICollector <DistanceHit> { // Transform the input into body space MTransform worldFromBody = new MTransform(WorldFromBody); MTransform bodyFromWorld = Inverse(worldFromBody); input.Position = Mul(bodyFromWorld, input.Position); SetQueryContextParameters(ref input.QueryContext, ref worldFromBody); return(Collider.IsCreated && Collider.Value.CalculateDistance(input, ref collector)); }
public bool DistanceLeaf <T>(PointDistanceInput input, int rigidBodyIndex, ref T collector) where T : struct, ICollector <DistanceHit> { rigidBodyIndex += BaseRigidBodyIndex; input.QueryContext.IsInitialized = true; input.QueryContext.RigidBodyIndex = rigidBodyIndex; RigidBody body = m_Bodies[rigidBodyIndex]; return(body.CalculateDistance(input, ref collector)); }
public static bool CalculateDistance <T>(ref T target, PointDistanceInput input, out DistanceHit result) where T : struct, ICollidable { var collector = new ClosestHitCollector <DistanceHit>(input.MaxDistance); if (target.CalculateDistance(input, ref collector)) { result = collector.ClosestHit; // TODO: would be nice to avoid this copy return(true); } result = new DistanceHit(); return(false); }
public unsafe void Execute( Entity entity, int index, [ReadOnly] ref PlayerTag tag, //[ReadOnly] ref GroundHitColliderData hit, [ReadOnly] ref Translation pos, ref PhysicsVelocity v ) { var upf = 0.0f; if (this.JumpForce > 0.0f) { //var hitInput = new ColliderCastInput //{ // Collider = (Collider*)hit.Collider.GetUnsafePtr(), // Orientation = quaternion.identity, // Start = pos.Value + math.up() * 0.05f, // End = pos.Value + math.up() * -0.1f, //}; var hitInput = new PointDistanceInput { Position = pos.Value, MaxDistance = 0.1f, Filter = new CollisionFilter { BelongsTo = (1 << 20) | (1 << 22) | (1 << 23), CollidesWith = (1 << 20) | (1 << 22) | (1 << 23), GroupIndex = 0, }, }; //var collector = new ExcludeEntityCollector //{ // IgnoreEntity = entity, // Rigidbodies = this.CollisionWorld.Bodies, //}; var a = new NativeList <DistanceHit>(Allocator.Temp); var isHit = this.CollisionWorld.CalculateDistance(hitInput, ref a); if (isHit && a.Length > 1) { upf = this.JumpForce * 0.5f; } a.Dispose(); } var vlinear = v.Linear; var xyDir = math.rotate(this.CamRotWorld, this.StickDir) * this.DeltaTime * 170; xyDir.y = vlinear.y + upf; v.Linear = math.min(xyDir, new float3(10, 1000, 10)); }
public unsafe static void PointRange(CollisionWorld world, float radius, uint mask, float3 pos, ref NativeList <DistanceHit> hits) { PointDistanceInput input = new PointDistanceInput() { MaxDistance = radius, Filter = new CollisionFilter() { CategoryBits = mask, MaskBits = mask, GroupIndex = 0 }, Position = pos }; world.CalculateDistance(input, ref hits); }
public static bool OverlapCircle(ISimGameWorldReadWriteAccessor accessor, fix2 position, fix radius, NativeList <DistanceHit> outHits, Entity ignoreEntity = default) { var physicsSystem = accessor.GetExistingSystem <PhysicsWorldSystem>(); PointDistanceInput pointDistanceInput = PointDistanceInput.Default; pointDistanceInput.MaxDistance = (float)radius; pointDistanceInput.Position = (float2)position; if (ignoreEntity != Entity.Null) { pointDistanceInput.Ignore = new IgnoreHit(physicsSystem.GetPhysicsBodyIndex(ignoreEntity)); } return(physicsSystem.PhysicsWorld.CalculateDistance(pointDistanceInput, ref outHits)); }
public bool CalculateDistance <T>(PointDistanceInput input, NativeArray <RigidBody> rigidBodies, ref T collector) where T : struct, ICollector <DistanceHit> { if (input.Filter.IsEmpty) { return(false); } var leafProcessor = new BvhLeafProcessor(rigidBodies); leafProcessor.BaseRigidBodyIndex = m_DynamicTree.NumBodies; bool hasHit = m_StaticTree.BoundingVolumeHierarchy.Distance(input, ref leafProcessor, ref collector); leafProcessor.BaseRigidBodyIndex = 0; hasHit |= m_DynamicTree.BoundingVolumeHierarchy.Distance(input, ref leafProcessor, ref collector); return(hasHit); }
public void Execute(Entity ent, int index, [ReadOnly] ref Translation translation, ref Enemy enemy) { enemy.timer -= deltaTime; var input = new PointDistanceInput() { MaxDistance = enemy.rangeDie, Filter = new CollisionFilter() { CategoryBits = mask, MaskBits = mask, GroupIndex = 0 }, Position = translation.Value }; DistanceHit hit; if (world.CalculateDistance(input, out hit)) { cmd.DestroyEntity(index, ent); cmd.DestroyEntity(index, world.Bodies[hit.RigidBodyIndex].Entity); var e = cmd.Instantiate(index, explosionPrefab); cmd.SetComponent(index, e, new Translation() { Value = hit.Position }); } else if (enemy.timer < 0) { input.MaxDistance = enemy.rangeShoot; if (world.CalculateDistance(input, out hit)) { var dir = hit.Position - translation.Value; dir *= enemy.rangeShoot / math.length(dir) * 0.5f; cmd.DestroyEntity(index, world.Bodies[hit.RigidBodyIndex].Entity); var e = cmd.Instantiate(index, lazerPrefab); cmd.SetComponent(index, e, new Translation() { Value = translation.Value + dir }); cmd.SetComponent(index, e, new Rotation() { Value = quaternion.RotateZ(math.atan2(dir.y, dir.x)) }); enemy.timer = enemy.cooldown; } } }
protected override void OnUpdate() { Entities.ForEach((ref Proximity proximity, ref Translation translation, ref PhysicsCollider collider) => { ref PhysicsWorld physicsWorld = ref World.DefaultGameObjectInjectionWorld.GetExistingSystem <BuildPhysicsWorld>().PhysicsWorld; if (collider.Value.IsCreated) { var pointDistanceInput = new PointDistanceInput { Position = translation.Value, MaxDistance = proximity.maxDistance, Filter = collider.Value.Value.Filter }; // Assign DistanceHit data to proximiy component physicsWorld.CalculateDistance(pointDistanceInput, out proximity.distanceHit); } }).WithoutBurst().Run();
public void Execute( Entity entity, int jobIndex, [WriteOnly] ref WallHitResultData result, [ReadOnly] ref GroundHitSphereData sphere, [WriteOnly] ref Translation pos, [WriteOnly] ref Rotation rot ) { //var rtf = new RigidTransform( rot.Value, pos.Value ); var hitInput = new PointDistanceInput { Position = pos.Value,//math.transform( rtf, sphere.Center ), MaxDistance = sphere.Distance, Filter = sphere.Filter, }; //var isHit = this.CollisionWorld.CalculateDistance( hitInput, ref a );// 自身のコライダを除外できればシンプルになるんだが… var collector = new ClosestHitExcludeSelfCollector <DistanceHit>(sphere.Distance, entity, this.MainEntities); //var collector = new ClosestHitCollector<DistanceHit>( sphere.Distance ); var isHit = this.CollisionWorld.CalculateDistance(hitInput, ref collector); if (collector.NumHits == 0) { return; } result.IsHit = true; var n = collector.ClosestHit.SurfaceNormal; var p = collector.ClosestHit.Position; pos.Value = p + n * sphere.Distance; var right = math.mul(rot.Value, new float3(1.0f, 0.0f, 0.0f)); var forward = math.cross(n, right); var safe_forward = math.select(math.forward(rot.Value), forward, math.dot(right, n) > 0.001f); rot.Value = quaternion.LookRotation(safe_forward, n); }
public void Execute() { var pointDistanceInput = new PointDistanceInput { Position = transData.Value, MaxDistance = laserData.range, Filter = CollisionFilter.Default }; if (collectAll) { physWorld.CalculateDistance(pointDistanceInput, ref distanceHits); } else { if (physWorld.CalculateDistance(pointDistanceInput, out Unity.Physics.DistanceHit hit)) { distanceHits.Add(hit); } } }
public void Execute(ref Translation translation) { NativeList <DistanceHit> hits = new NativeList <DistanceHit>(Allocator.Temp); CollisionFilter targetFilter = new CollisionFilter() { BelongsTo = ~0u, CollidesWith = 8u, GroupIndex = 0 }; var pointDistanceInput = new PointDistanceInput { Position = translation.Value, MaxDistance = 50, Filter = targetFilter }; physicsWorld.CalculateDistance(pointDistanceInput, ref hits); hits.Dispose(); }
public unsafe static bool PointRangeSingle2(CollisionWorld world, float radius, uint mask, float3 pos, out DistanceHit hit) { var rayCommands = new NativeArray <PointDistanceInput>(1, Allocator.TempJob); var rayResults = new NativeArray <DistanceHit>(1, Allocator.TempJob); rayCommands[0] = new PointDistanceInput() { MaxDistance = radius, Filter = new CollisionFilter() { CategoryBits = mask, MaskBits = mask, GroupIndex = 0 }, Position = pos }; var handle = PointRanges(world, rayCommands, rayResults); handle.Complete(); hit = rayResults[0]; rayCommands.Dispose(); rayResults.Dispose(); return(hit.RigidBodyIndex != -1); }
private void Start() { LightningBoltGraphicEntityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(MainReferences.lightningTowerManager.LightningBoltGraphicPrefab, GameDataManager.instance.Settings); PhysicalBouncerEntityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(MainReferences.physicalTowerManager.PhysicalBouncerPrefab, GameDataManager.instance.Settings); PhysicalBounderNoGraphicsEntityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(MainReferences.physicalTowerManager.PhysicalBouncerNoGraphicsPrefab, GameDataManager.instance.Settings); EnemyDistanceHits = new NativeList <DistanceHit>(Allocator.Persistent); BulletEnemyCollisionFilter = new CollisionFilter { BelongsTo = 1 << 1, CollidesWith = 1 }; PointDistanceInput = new PointDistanceInput { Position = Vector3.zero, MaxDistance = 0, Filter = BulletEnemyCollisionFilter }; }
protected override JobHandle OnUpdate(JobHandle inputDeps) { _stepPhysicsWorld.FinalJobHandle.Complete(); var distanceHit = new NativeList <DistanceHit>(1, Allocator.TempJob); Entities.WithoutBurst() .ForEach((Entity entity, ref PhysicsCastData physicsCastData, in Translation position, in DistanceInputCommandData distanceInputCommandData) => { var pointDistanceInput = new PointDistanceInput { Position = position.Value, MaxDistance = distanceInputCommandData.maxDistance, Filter = distanceInputCommandData.collision }; var pointDistanceJobHandle = new PointDistanceJob { pointDistanceInput = pointDistanceInput, physicsWorld = _physicsWorld, distanceHits = distanceHit }.Schedule(); pointDistanceJobHandle.Complete(); if (distanceHit.Length > 0) { physicsCastData.entity = distanceHit[0].Entity; physicsCastData.hasTarget = true; physicsCastData.status = Status.Targetable; } else { physicsCastData.hasTarget = false; physicsCastData.status = Status.Idle; } })
public unsafe void Execute( Entity entity, int index, [WriteOnly] ref GroundHitResultData ground, [ReadOnly] ref GroundHitSphereData sphere, [ReadOnly] ref Translation pos, [ReadOnly] ref Rotation rot ) { //var a = new NativeList<DistanceHit>( Allocator.Temp ); var rtf = new RigidTransform(rot.Value, pos.Value); var hitInput = new PointDistanceInput { Position = math.transform(rtf, sphere.Center), MaxDistance = sphere.Distance, Filter = sphere.Filter, }; //var isHit = this.CollisionWorld.CalculateDistance( hitInput, ref a );// 自身のコライダを除外できればシンプルになるんだが… var collector = new AnyHitExcludeSelfCollector <DistanceHit>(sphere.Distance, entity, this.MainEntities); var isHit = this.CollisionWorld.CalculateDistance(hitInput, ref collector); //var castInput = new RaycastInput //{ // Start = math.transform( rtf, sphere.Center ), // End = math.transform( rtf, sphere.Center ) + ( math.up() * -sphere.Distance ), // Filter = sphere.filter, //}; //var collector = new AnyHitExcludeSelfCollector2( 1.0f, entity, this.CollisionWorld.Bodies ); //var isHit = this.CollisionWorld.CastRay( castInput, ref collector ); //ground = new GroundHitResultData { IsGround = ( isHit && a.Length > 1 ) }; //ground.IsGround = a.Length > 1; ground.IsGround = collector.NumHits > 0; //ground.IsGround = isHit; //a.Dispose(); }
protected override unsafe void OnUpdate() { CollisionWorld collisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld; CollisionFilter collisionFilter = new CollisionFilter() { BelongsTo = 1u << 0, CollidesWith = 0u | (1u << 0) | (1u << 1), GroupIndex = 0 }; Dependency = Entities.WithAll <AnimalTag>().ForEach((ref Translation translation, ref AnimalMovementData mvmtData, in PhysicsCollider collider, in Rotation rotation) => { Unity.Collections.NativeList <DistanceHit> hits = new Unity.Collections.NativeList <DistanceHit>(Unity.Collections.Allocator.Temp); float maxDist = 1f; float3 fwd = translation.Value + (mvmtData.targetDirection * 0.25f); // Tested in Unity 2020.1.0b10 //ColliderDistanceInput cdi = new ColliderDistanceInput() //{ // Collider = collider.ColliderPtr, // MaxDistance = maxDist, // Transform = new RigidTransform(rotation.Value, translation.Value) //}; PointDistanceInput pdi = new PointDistanceInput() { Filter = collisionFilter, MaxDistance = maxDist, Position = fwd }; if (collisionWorld.CalculateDistance(pdi, ref hits)) { DistanceHit closest = GetClosestHit(hits, maxDist); if (closest.Distance > 0.00001) { float distance = closest.Distance; float distanceFrac = 1 - (distance / maxDist); distanceFrac = math.clamp(distanceFrac, 0.25f, 1f); byte colliderTags = collisionWorld.Bodies[closest.RigidBodyIndex].CustomTags; float dotProduct = 0f; float angle = 0f; bool avoid = false; if (colliderTags == 1) // Collision with another animal { quaternion r = collisionWorld.Bodies[closest.RigidBodyIndex].WorldFromBody.rot; float3 othersFwd = math.rotate(r, new float3(0f, 0f, 1f)); dotProduct = (float)(math.dot(mvmtData.targetDirection, math.normalize(othersFwd))); if (dotProduct < -0.7f) { avoid = true; angle = 5.846853f * distanceFrac; //- 25f degrees } else if (dotProduct >= -0.001f && dotProduct < 0.975f) { avoid = true; angle = (0.436332f - math.acos(dotProduct)) * distanceFrac; // 25 degrees } } else if (colliderTags == 2) // Collision with terrain { dotProduct = math.dot(mvmtData.targetDirection, math.normalize(closest.SurfaceNormal)); if (dotProduct < -0.1f) { avoid = true; angle = -(1.570796f - math.acos(dotProduct)) * distanceFrac; //90 degrees -> parallel to surface normal } } if (avoid) { quaternion newRotation = quaternion.RotateY(angle); float3 newDirection = math.rotate(newRotation, mvmtData.direction); newDirection = math.normalizesafe(newDirection); mvmtData.targetDirection = newDirection; } } } hits.Dispose(); }).Schedule(Dependency);
public void Execute( Entity entity, int index, ref VelocityComponent velocityComponent, ref Translation translation ) { velocityComponent.timerCalcVelocity -= DeltaTime; if (velocityComponent.timerCalcVelocity > 0) { return; } velocityComponent.timerCalcVelocity = tick; var input = new PointDistanceInput { Position = translation.Value, MaxDistance = cohesionRadius, Filter = CollisionFilter }; var closestHits = new NativeList <DistanceHit>(Allocator.Temp); if (!CollisionWorld.CalculateDistance(input, ref closestHits)) { closestHits.Dispose(); return; } if (closestHits.Length < 2) { closestHits.Dispose(); return; } velocityComponent.cohesion = float3.zero; velocityComponent.separation = float3.zero; velocityComponent.separationCount = 0; velocityComponent.alignment = float3.zero; for (int i = 0; i < closestHits.Length && i < maxBoids; i++) { var entityHit = CollisionWorld.Bodies[closestHits[i].RigidBodyIndex].Entity; velocityComponent.vector = translation.Value - TranslationMapData[entityHit].Value; velocityComponent.sqrMagnitude = Vector3.SqrMagnitude(velocityComponent.vector); velocityComponent.cohesion += TranslationMapData[entityHit].Value; velocityComponent.alignment += VelocityMapData[entityHit].velocity; if (velocityComponent.sqrMagnitude > 0 && velocityComponent.sqrMagnitude < separationDistance2) { velocityComponent.separation += velocityComponent.vector / velocityComponent.sqrMagnitude; velocityComponent.separationCount++; } } velocityComponent.cohesion /= closestHits.Length > maxBoids ? maxBoids : closestHits.Length; velocityComponent.cohesion = Vector3.ClampMagnitude(velocityComponent.cohesion - translation.Value, maxSpeed); velocityComponent.cohesion *= cohesionCoefficient; if (velocityComponent.separationCount > 0) { velocityComponent.separation /= velocityComponent.separationCount; velocityComponent.separation = Vector3.ClampMagnitude(velocityComponent.separation, maxSpeed); velocityComponent.separation *= separationCoefficient; } velocityComponent.alignment /= closestHits.Length > maxBoids ? maxBoids : closestHits.Length; velocityComponent.alignment = Vector3.ClampMagnitude(velocityComponent.alignment, maxSpeed); velocityComponent.alignment *= alignmentCoefficient; velocityComponent.velocity = Vector3.ClampMagnitude(velocityComponent.cohesion + velocityComponent.separation + velocityComponent.alignment, maxSpeed); closestHits.Dispose(); }
public static bool CalculateDistance <T>(ref T target, PointDistanceInput input, ref NativeList <DistanceHit> allHits) where T : struct, ICollidable { var collector = new AllHitsCollector <DistanceHit>(input.MaxDistance, ref allHits); return(target.CalculateDistance(input, ref collector)); }
public bool CalculateDistance(PointDistanceInput input, ref NativeList <DistanceHit> allHits) => QueryWrappers.CalculateDistance(ref this, input, ref allHits);
public static bool CalculateDistance <T>(ref T target, PointDistanceInput input) where T : struct, ICollidable { var collector = new AnyHitCollector <DistanceHit>(input.MaxDistance); return(target.CalculateDistance(input, ref collector)); }
public bool CalculateDistance <T>(PointDistanceInput input, ref T collector) where T : struct, ICollector <DistanceHit> { return(CollisionWorld.CalculateDistance(input, ref collector)); }