internal static void Query(Protocol.QueryPayload payload) { MessagingBus.QueuedSceneMessage_Scene queuedMessage = GetSceneMessageInstance(); string queryId = Convert.ToString(payload.raycastPayload.id); RaycastType raycastType = (RaycastType)payload.raycastPayload.raycastType; Ray ray = new Ray() { origin = payload.raycastPayload.origin, direction = payload.raycastPayload.direction, distance = payload.raycastPayload.distance }; queuedMessage.method = MessagingTypes.QUERY; queuedMessage.payload = new QueryMessage() { payload = new RaycastQuery() { id = queryId, raycastType = raycastType, ray = ray, sceneId = currentSceneId } }; queueHandler.EnqueueSceneMessage(queuedMessage); }
public RaycastSensor(RaycastType type, Vector3 direction, float distance, bool hitObject = false) { Type = type; Direction = direction; Distance = distance; HitObject = hitObject; }
/// <summary> /// Returns true if the this raycast type is or contains the given raycast type. /// </summary> /// <param name="go">Go.</param> /// <param name="type">Type.</param> public static bool Contains(this RaycastType container, RaycastType type) { if ((container & type) == type) { return(true); } return(false); }
bool raycast(Vector2 origin, Vector2 target, Layer layer, RaycastType rcType) { var ray = origin; var angle = MathHelper.PiOver2 - (float)Math.Atan2(ray.Y - target.Y, ray.X - target.X); while ((ray - target).Length() > 10) { if (rcType == RaycastType.Hit && _map.Layers[(int)layer].Tiles[GridToIndex(WorldToGrid(ray))].Gid != 0) { return(true); } ray += new Vector2((float)Math.Sin(angle) * -2, (float)Math.Cos(angle) * -2); } return(rcType == RaycastType.Hit ? false : true); }
private void Raycast(Vector2 from, Vector2 to, RaycastType rayType) { bool hitDetected = false; hits = Physics2D.LinecastAll(from, to); //Iterate results foreach (RaycastHit2D hit in hits) { //Check if collider exists and is not the collider attached to target transform (self) if (hit.collider != null && hit.collider.transform != target) { hitDetected = true; HandleHit(hit); } } #region Debug rays if (showDebugRays) { Color lineColor = Color.white; switch (rayType) { case RaycastType.Horizontal: lineColor = Color.white; break; case RaycastType.Vertical: lineColor = Color.cyan; break; case RaycastType.IntersectionTop: lineColor = Color.magenta; break; case RaycastType.IntersectionBottom: lineColor = Color.yellow; break; } //Red whenever it hits something Debug.DrawLine(from, to, hitDetected ? Color.red : lineColor, debugRayLifetime); } #endregion }
/// <summary> /// Check for a gap by casting rays extending along the side colldiers. /// </summary> /// <returns><c>true</c>, if gap dection from side colliders was done, <c>false</c> otherwise.</returns> virtual protected bool DoGapDectionFromSideColliders() { RaycastType typeToCheck = character.Colliders [character.CurrentWallCollider].RaycastType; // Determine how much to offset the raycasts from ledge position Vector2 transformOffset = Vector2.zero; switch (animationTargetting) { case LedgeClimbAnimationTargetting.SPRITE_PIVOT: // For a sprite pivot use the stand offset transformOffset = standOffset; if (typeToCheck == RaycastType.SIDE_RIGHT) { transformOffset.x = transformOffset.x * -1; } break; case LedgeClimbAnimationTargetting.BAKED: // For a sprite pivot use the stand offset transformOffset = standOffset; if (typeToCheck == RaycastType.SIDE_RIGHT) { transformOffset.x = transformOffset.x * -1; } break; } foreach (BasicRaycast c in character.Colliders) { // If collider is of the right type if (c.RaycastType == typeToCheck) { Vector2 finalPosition = CurrentLedgePosition + c.Extent + transformOffset; Vector2 initialPosition = new Vector2(character.transform.position.x, finalPosition.y); Vector2 direction = (finalPosition - initialPosition).normalized; float distance = Mathf.Abs(finalPosition.x - character.transform.position.x); RaycastHit2D hit = Physics2D.Raycast(initialPosition, direction, distance, character.geometryLayerMask); if (hit.collider != null) { return(false); } } } return(true); }
private void DrawPhysics1() // 射线检测 { m_RaycastType = (RaycastType)m_Tools.BiaoTi_O(m_RaycastType, (int)m_RaycastType, RaycastTypeStrs, 60); switch (m_RaycastType) { case RaycastType.Physics_Raycast: DrawPhysicsRaycast(); break; case RaycastType.Physics_RaycastAll: DrawPhysicsRaycastAll(); break; case RaycastType.Physics2D_Raycast: DrawPhysics2DRaycast(); break; } }
/// <summary> /// Checks the given collisions type for enemies. /// </summary> /// <returns>Returns an IHurtable if found, or null if not found.</returns> virtual protected IHurtable CheckCollisions(RaycastType type) { for (int i = 0; i < character.Colliders.Length; i++) { if (character.Colliders[i].RaycastType == type) { for (int j = 0; j < character.CurrentCollisions[i].Length; j++) { if (character.CurrentCollisions[i][j].collider != null && ((1 << character.CurrentCollisions[i][j].collider.gameObject.layer & enemyLayerMask) == enemyLayerMask)) { IHurtable enemyHurtBox = (IHurtable)character.CurrentCollisions[i][j].collider.GetComponent(typeof(IHurtable)); if (enemyHurtBox != null) { return(enemyHurtBox); } } } } } return(null); }
public static void ReportRaycastHitAllResult(string sceneId, string queryId, RaycastType raycastType, RaycastHitEntities payload) { ReportRaycastResult <RaycastHitAllResponse, RaycastHitEntities>(sceneId, queryId, Protocol.RaycastTypeToLiteral(raycastType), payload); }
/// <summary> /// Check for collider penetration of the given types on the given layers and move the character if found. /// </summary> /// <param name="typeMask">The types to consider.</param> /// <param name="layerMask">The layers to consider.</param> /// <returns>A vector representing the amount of movement applied.</returns> virtual public Vector2 DoCollisions(RaycastType typeMask, int layerMask, int passthroughLayerMask) { Vector2 result = Vector2.zero; float deepestSidePenetration = 0.0f; float deepestHeadPenetration = 0.0f; float deepestFootPenetration = 0.0f; float deepestNonPassthroughFootPenetration = 0.0f; int sideIndex = -1; int headIndex = -1; int footIndex = -1; int nonPassthroughFootIndex = -1; int groundedFeetCount = 0; int passthroughFeetCount = 0; int layer; bool parentFound = false; // TODO could we just do this every frame only sending a message once even if multiple collider types hit the collider? ResetCollisions(); // If we are doing feet collisions update grounded if ((RaycastType.FOOT & typeMask) == RaycastType.FOOT) { grounded = false; if (character is Character) { ((Character)character).StoodOnPlatform = null; ((Character)character).GroundLayer = -1; ((Character)character).GroundCollider = null; } } // If we are moving in Y assume we aren't grounded // if (character.Velocity.y != 0 ) grounded = false; // Get the closest collision - TODO: we have similar code in character too, its (very slightly) more efficient this way but maybe easier to maintain if we reuse? for (int i = 0; i < character.CurrentCollisions.Length; i++) { // If we are considering this type of collider if ((character.Colliders[i].RaycastType & typeMask) == character.Colliders[i].RaycastType) { int closest = -1; float smallestFraction = float.MaxValue; Platform platform = null; for (int j = 0; j < character.CurrentCollisions[i].Length; j++) { // Make sure we have a collision to support raycast colliders which use statically allocated hits arrays if (character.CurrentCollisions[i][j].collider != null) { // Correct layer? layer = character.CurrentCollisions[i][j].collider.gameObject.layer; if ((1 << layer & layerMask) == 1 << layer || (character.Colliders[i].RaycastType == RaycastType.FOOT && (1 << layer & passthroughLayerMask) == 1 << layer)) { if (character.CurrentCollisions[i][j].fraction > 0 && character.CurrentCollisions[i][j].fraction < smallestFraction) { // The memory allocation only occurs in the editor, its not the GC trap that is seems Platform tmpPlatform = character.CurrentCollisions[i][j].collider.GetComponent <Platform>(); if (tmpPlatform == null || !tmpPlatform.IgnoreCollision(character, character.Colliders[i])) { smallestFraction = character.CurrentCollisions[i][j].fraction; closest = j; platform = tmpPlatform; } } } } } // Store the closest collider closestColliders[i] = closest; // Found a collision if (closest != -1) { layer = character.CurrentCollisions[i][closest].collider.gameObject.layer; float penetration = (character.CurrentCollisions[i][closest].fraction * (character.Colliders[i].Length + character.Colliders[i].LookAhead)) - character.Colliders[i].Length; switch (character.Colliders[i].RaycastType) { case RaycastType.SIDE_LEFT: if (penetration < deepestSidePenetration) { deepestSidePenetration = penetration; sideIndex = i; } // Check for platforms // TODO We may need a new lookahead if condition here. If the grounded look ahead // was large we may be triggering platforms too early. if (!HasReceivedCollideMessage(character.CurrentCollisions[i][closest].collider)) { platformCollisionArgs.Character = character; platformCollisionArgs.RaycastCollider = character.Colliders[i]; platformCollisionArgs.Penetration = penetration; if (platform != null) { bool parent = platform.Collide(platformCollisionArgs); if (parent) { parentFound = true; character.ParentPlatform = platform; character.ParentRaycastType = RaycastType.SIDE_LEFT; } AddColliderToSentMessageReceivers(character.CurrentCollisions[i][closest].collider); } } break; case RaycastType.SIDE_RIGHT: if (penetration < deepestSidePenetration) { deepestSidePenetration = penetration; sideIndex = i; } // Check for platforms // TODO We may need a new lookahead if condition here. If the grounded look ahead // was large we may be triggering platforms too early. if (!HasReceivedCollideMessage(character.CurrentCollisions[i][closest].collider)) { platformCollisionArgs.Character = character; platformCollisionArgs.RaycastCollider = character.Colliders[i]; platformCollisionArgs.Penetration = penetration; if (platform != null) { bool parent = platform.Collide(platformCollisionArgs); if (parent) { parentFound = true; character.ParentPlatform = platform; character.ParentRaycastType = RaycastType.SIDE_RIGHT; } AddColliderToSentMessageReceivers(character.CurrentCollisions[i][closest].collider); } } break; case RaycastType.HEAD: if (penetration < deepestHeadPenetration) { deepestHeadPenetration = penetration; headIndex = i; } // Check for platforms // TODO We may need a new lookahead if condition here. If the head look ahead // was large we may be triggering platforms too early. if (!HasReceivedCollideMessage(character.CurrentCollisions[i][closest].collider)) { platformCollisionArgs.Character = character; platformCollisionArgs.RaycastCollider = character.Colliders[i]; platformCollisionArgs.Penetration = penetration; if (platform != null) { bool parent = platform.Collide(platformCollisionArgs); if (parent) { parentFound = true; character.ParentPlatform = platform; character.ParentRaycastType = RaycastType.HEAD; } AddColliderToSentMessageReceivers(character.CurrentCollisions[i][closest].collider); } } character.WouldHitHeadThisFrame = true; break; case RaycastType.FOOT: if (penetration < deepestFootPenetration) { deepestFootPenetration = penetration; footIndex = i; } // Keep track of non passthrough feet collisions as these should be applied even if passthrough is deeper if (((1 << layer & passthroughLayerMask) != 1 << layer) && penetration < deepestNonPassthroughFootPenetration) { deepestNonPassthroughFootPenetration = penetration; nonPassthroughFootIndex = i; } // Check for platforms // TODO We may need a new lookahead if condition here. If the grounded look ahead // was large we may be triggering platforms too early. if (!HasReceivedCollideMessage(character.CurrentCollisions[i][closest].collider)) { platformCollisionArgs.Character = character; platformCollisionArgs.RaycastCollider = character.Colliders[i]; platformCollisionArgs.Penetration = penetration; if (platform != null) { bool parent = platform.Collide(platformCollisionArgs); if (parent) { parentFound = true; character.ParentPlatform = platform; character.ParentRaycastType = RaycastType.FOOT; } AddColliderToSentMessageReceivers(character.CurrentCollisions[i][closest].collider); // TODO: Currently we just take whichever is last in the feet collider array // we could update this to handle multiple platforms. character.StoodOnPlatform = platform; } } if (penetration <= character.groundedLookAhead) { // Keep track of how many passthrough feet we have if ((1 << layer & passthroughLayerMask) == 1 << layer) { passthroughFeetCount++; // TODO consider if this should be user configurable? if (character.Velocity.y <= 0 && penetration > character.passthroughLeeway) { // Set grounded only if we are moving downwards grounded = true; // Keep track of how many feet we have grounded groundedFeetCount++; // Set layer if its not set or if this is the middle foot collider if (character.GroundLayer == -1 || i == character.FootCount / 2) { character.GroundLayer = layer; character.GroundCollider = character.CurrentCollisions[i][closest].collider; } } } else { // Set grounded grounded = true; // Keep track of how many feet we have grounded groundedFeetCount++; // Set layer if its not set or if this is the middle foot collider if (character.GroundLayer == -1 || i == character.FootCount / 2) { character.GroundLayer = layer; character.GroundCollider = character.CurrentCollisions[i][closest].collider; } } } break; default: Debug.LogError("Unexpected collider type"); break; } } } } // If we had penetration apply movement if (sideIndex != -1 && deepestSidePenetration < 0) { result.x = deepestSidePenetration * (character.Colliders[sideIndex].RaycastType == RaycastType.SIDE_LEFT ? -1 : 1); character.Translate(result.x, 0, false); if (!character.ActiveMovement.PreventXVelocityReset) { if ((character.Velocity.x > 0 && character.Colliders[sideIndex].RaycastType == RaycastType.SIDE_RIGHT) || (character.Velocity.x < 0 && character.Colliders[sideIndex].RaycastType == RaycastType.SIDE_LEFT)) { character.SetVelocityX(0); } } // character.SetVelocityY(character.Velocity.y); } // Always apply geometry layer feet collisions if (nonPassthroughFootIndex != -1 && deepestNonPassthroughFootPenetration < 0) { result.y = -deepestNonPassthroughFootPenetration; character.Translate(0, -deepestNonPassthroughFootPenetration, false); // If we were moving down reset Y velocity to 0 if (character.Velocity.y < 0) { character.SetVelocityY(0); } } // Check for passthrough feet too if (footIndex != -1 && footIndex != nonPassthroughFootIndex && deepestFootPenetration < deepestNonPassthroughFootPenetration) { // Ensure we calculate the time to move feet distance if (!assumeConstantGravityAndFeetDistance && character.Colliders[footIndex].RaycastType == RaycastType.FOOT) { if (character.Gravity < 0) { timeToFallFeetDistance = Mathf.Sqrt((-2 * character.Colliders[footIndex].Length) / character.Gravity); } } // Additional conditions for passthrough feet if (character.Velocity.y <= 0 && (grounded || character.TimeFalling >= timeToFallFeetDistance)) { result.y = -deepestFootPenetration; character.Translate(0, -deepestFootPenetration, false); // If we were moving down reset Y velocity to 0 if (character.Velocity.y < 0) { character.SetVelocityY(0); } } } if (headIndex != -1 & deepestHeadPenetration < 0) { result.y = deepestHeadPenetration; character.Translate(0, deepestHeadPenetration, false); // If we were moving up reset Y velocity to 0 if (character.Velocity.y > 0) { character.SetVelocityY(0); } } // If we are doing feet collisions update parent state if (((character.ParentRaycastType & typeMask) == character.ParentRaycastType) && !parentFound) { character.ParentPlatform = null; } // If we are doing feet collisions update grounded if ((RaycastType.FOOT & typeMask) == RaycastType.FOOT) { character.GroundedFootCount = groundedFeetCount; } return(result); }
/// <summary> /// Gets a value indicating whether this movement wants to control the movement on the ground. /// This movement wants control if the side colliders are pulling a box. /// </summary> /// <value><c>true</c> if this instance wants control; otherwise, <c>false</c>.</value> override public bool WantsGroundControl() { if (!enabled) { return(false); } if (character.DefaultGroundMovement == this) { Debug.LogError("The Pull movement can't be the default ground movement. Disabling movement."); enabled = false; } // Early out, only pull if grounded. if (!character.Grounded) { LosingControl(); return(false); } // Early out, if last frame we were pulling one way, we want to lose control for at least one frame before pulling another way if (!latched && pullDirection == -character.Input.HorizontalAxisDigital) { LosingControl(); return(false); } // Early out, if we were pulling, and our velocity is non zero and we are still holding down pull keep going if (pullable != null && !latched && pullDirection == character.Input.HorizontalAxisDigital && character.Velocity.x != 0) { return(true); } // If we are latched check if we are still latched if (latched && pullable != null) { if (character.Input.HorizontalAxisDigital == -pullDirection || character.Input.HorizontalAxisDigital == 0) { if (latchTimer <= 0) { LosingControl(); } return(false); } // Start pulling if (character.Input.HorizontalAxisDigital == pullDirection) { latched = false; pullDelayTimer = PullDelayTime; return(true); } } // Try to find a pullable int hitCount = 0; IPullable matchingPullable = null; float pullableDistance = 1; float nonPullableDistance = 1; RaycastType typeToCheck = (character.Input.HorizontalAxisDigital == 1 ? RaycastType.SIDE_RIGHT : RaycastType.SIDE_LEFT); initialPullOffset = 0; for (int i = 0; i < character.Colliders.Length; i++) { if (character.Colliders[i].RaycastType == typeToCheck) { RaycastHit2D hit = character.GetClosestCollision(i); if (hit.collider != null) { IPullable currentPullable = (IPullable)hit.collider.GetComponent(typeof(IPullable)); // Pulling something that isn't pushable TODO add distance checks. if (currentPullable == null) { if (hit.fraction < nonPullableDistance) { nonPullableDistance = hit.fraction; } } else { if (currentPullable != matchingPullable) { // Found a closer pushable (or if matching pushable is null we just found a pushable) if (hit.fraction < pullableDistance) { pullableDistance = hit.fraction; matchingPullable = currentPullable; initialPullOffset = (hit.fraction * (character.Colliders[i].Length + character.Colliders[i].LookAhead)) - character.Colliders[i].Length - character.Colliders[i].LookAhead; hitCount = 1; } } else { hitCount++; } } } } } if (matchingPullable != null && pullableDistance < nonPullableDistance && initialPullOffset < 0) { pullable = matchingPullable; initialPullOffset *= -character.Input.HorizontalAxisDigital; pullDirection = -character.Input.HorizontalAxisDigital; latched = true; latchTimer = LatchTime; } return(false); }
public WindowRaycastNode(WindowSection section_, Vector3 pos_, RaycastType type_) { section = section_; pos = pos_; type = type_; }
/// <summary> /// Utility method which checks for side collissions. /// </summary> /// <returns><c>true</c>, if sides hit something, <c>false</c> otherwise.</returns> /// <param name="character">Character to check.</param> /// <param name="requiredHits">Required number of side hits.</param> /// <param name="types">Side types to check.</param> static public bool CheckSideCollisions(Character character, int requiredHits, RaycastType types) { int hitCount = 0; for (int i = 0; i < character.Colliders.Length; i++) { if ((character.Colliders[i].RaycastType & types) == character.Colliders[i].RaycastType) { RaycastHit2D hit = character.GetClosestCollision(i); if (hit.collider != null) { hitCount++; if (hitCount >= requiredHits) { return(true); } } } } return(false); }
public void UseCenter() { castType = RaycastType.Center; CastRay(); }
// ---- public methods ---- public void UseMouse() { castType = RaycastType.Mouse; CastRay(); }
/// <summary> /// Utility method which checks for side collissions. /// </summary> /// <returns><c>true</c>, if sides hit something, <c>false</c> otherwise.</returns> /// <param name="character">Character to check.</param> /// <param name="requiredHits">Required number of side hits.</param> /// <param name="types">Side types to check.</param> public static bool CheckSideCollisions(Character character, int requiredHits, RaycastType types) { int hitCount = 0; for (int i = 0; i < character.Colliders.Length; i++) { if ((character.Colliders[i].RaycastType & types) == character.Colliders[i].RaycastType) { RaycastHit2D hit = character.GetClosestCollision(i); if (hit.collider != null) { hitCount++; if (hitCount >= requiredHits) return true; } } } return false; }
/// <summary> /// Gets a value indicating whether this movement wants to control the movement on the ground. /// This movement wants control if the side colliders are pushing against a box. /// </summary> /// <value><c>true</c> if this instance wants control; otherwise, <c>false</c>.</value> override public bool WantsGroundControl() { if (!enabled) { return(false); } if (character.DefaultGroundMovement == this) { Debug.LogError("The Push movement can't be the default ground movement. Disabling movement."); enabled = false; } // Early out, only push if grounded. if (!character.Grounded) { return(false); } // Early out, only push if pressing in a direction. if (character.Input.HorizontalAxisDigital == 0) { return(false); } // Early out, if last frame we were pusing one way, we want to lose control for at least one frame before pushing another way if (pushDirection == -character.Input.HorizontalAxisDigital) { return(false); } int hitCount = 0; Pushable matchingPushable = null; float pushableDistance = 1; float nonPushableDistance = 1; RaycastType typeToCheck = (character.Input.HorizontalAxisDigital == 1 ? RaycastType.SIDE_RIGHT : RaycastType.SIDE_LEFT); initialPushOffset = 0; for (int i = 0; i < character.Colliders.Length; i++) { if (character.Colliders[i].RaycastType == typeToCheck) { RaycastHit2D hit = character.GetClosestCollision(i); if (hit.collider != null) { Pushable currentPushable = hit.collider.GetComponent <Pushable>(); // Pushing against something that isn't pushable TODO add distance checks. if (currentPushable == null) { if (hit.fraction < nonPushableDistance) { nonPushableDistance = hit.fraction; } } else { if (currentPushable != matchingPushable) { // Found a closer pushable (or if matching pushable is null we just found a pushable) if (hit.fraction < pushableDistance) { pushableDistance = hit.fraction; matchingPushable = currentPushable; initialPushOffset = (hit.fraction * (character.Colliders[i].Length + character.Colliders[i].LookAhead)) - character.Colliders[i].Length - character.Colliders[i].LookAhead; hitCount = 1; } } else { hitCount++; } } } } } if (matchingPushable != null && pushableDistance < nonPushableDistance && initialPushOffset < 0) { pushable = matchingPushable; initialPushOffset *= -character.Input.HorizontalAxisDigital; pushDirection = character.Input.HorizontalAxisDigital; return(true); } return(false); }