private void PhysicsEffect(Vector3 point, Vector3 normal) { if (physicsMode == PhysicsMode.Scattered) { PhysicsUtilities.CopyAllRigidbodies(); PhysicsUtilities.DeleteRigidBodiesNotInParent(rootContainer); } switch (physicsEffects) { case PhysicsEffects.Explosion: PhysicsUtilities.AddExplosion(point, normal); break; case PhysicsEffects.BlackHole: PhysicsUtilities.AddBlackHole(point, normal); break; case PhysicsEffects.SimpleForce: PhysicsUtilities.AddSimpleForce(point, normal); break; } if (physicsMode == PhysicsMode.Scattered) { PhysicsUtilities.PasteRigidbodies(); var rigidbodyContainer = GameObject.Find("Rigidbody Container"); GameObject.DestroyImmediate(rigidbodyContainer); } PhysicsUtilities.ActivatePhysics(); }
public void SetParticleSpawnInfoValues(GameObject particlePrefab, Actor myActor = null, Animator myAnimator = null) { actor = myActor; if (myAnimator != null) { parent = myAnimator.transform; if (useHumanoidRigLocation) { parent = myAnimator.GetBoneTransform(humanoidRigLocation); } } if (parent) { SpawnPosition = parent.transform.position + parent.transform.TransformDirection(PositionOffset); } if (onGround) { SpawnPosition = PhysicsUtilities.FindPointOnGround(SpawnPosition); SpawnPosition += new Vector3(0, .01f, 0); } SpawnRotation = usePrefabRotation ? particlePrefab.transform.rotation : parent.rotation; if (worldSpace) { parent = null; } }
void OnCollisionEnter2D(Collision2D col) { // do this check so the collision is only called once - failsafe against unity physics engine if (_isColliding) { return; } _isColliding = true; // only check for collisions with the player is the steel crate's gravity is enabled if (gravEnabled && col.gameObject.CompareTag("Player")) { Transform groundCheck = col.gameObject.transform.GetChild(0); Vector2 posOffset = (Vector2)transform.position + PhysicsUtilities.OffsetToEdgeRenderer(rend); // NEED TO FIND OUT HOW TO NOT DESTROY INSTANTLY WHILE IN GRAV TRANSITION // FOR SOME REASON THE BELOW DOES NOT WORK if (!GameController.gravTransitionState && PhysicsUtilities.IsBelow(groundCheck.position, posOffset)) { Destroy(col.gameObject); } // to be added: enter gameover state } // handle check for glass if (isGlass && GameController.gravTransitionState) { if (_glass.CollisionHandler(rend)) { Destroy(gameObject); } } }
public void OnInteract(Actor actor) { var v = orientation * vec3.UnitX; // This determins which side of the door is being opened. if (Utilities.Dot(v, actor.Position - position) < 0) { v *= -1; } // TODO: Retrieve static map body in a better way. var world = Scene.World; var body = world.RigidBodies.First(b => b.BodyType == RigidBodyTypes.Static && b.Shape is TriangleMeshShape); if (!PhysicsUtilities.Raycast(world, body, position + v, -vec3.UnitY, RaycastLength, out var results)) { Debug.Fail("Door raycast failed (this likely means that the raycast length needs to be extended)."); } // TODO: To animate properly, probably need to mark the body manually-controlled and apply step. actor.GroundPosition = results.Position; actor.ControllingBody.LinearVelocity = JVector.Zero; var player = (PlayerCharacter)actor; player.Lock(); // Attaching a null controller freezes the camera in place while the door opens. Scene.Camera.Attach(null); }
// set up facings and zRot values protected void SetFacingsAndZRot() { zRot = (int)transform.eulerAngles.z; // set z rotation // set facing and opposite facing depending on the z rotation facing = PhysicsUtilities.GetFacingDirection(zRot); oppositeFacing = PhysicsUtilities.GetFacingDirection(zRot, true); }
public override void PostStep(float step) { // Floor raycasts are based on step height. The intention is to snap smoothly going both up and down stairs // (which should also work fine for normal triangles, which are much less vertically-separated than steps). const float RaycastMultiplier = 1.2f; const float Epsilon = 0.001f; var body = Parent.ControllingBody; var halfHeight = new vec3(0, Parent.FullHeight / 2, 0); var p = body.Position.ToVec3() - halfHeight; var ground = Parent.Ground; // If the projection returns true, that means the actor is still within the current triangle. if (ground.Project(p, out vec3 result)) { // This helps prevent very, very slow drift while supposedly stationary (on the order of 0.0001 per // second). if (Utilities.DistanceSquared(p, result) > Epsilon) { body.Position = (result + halfHeight).ToJVector(); } return; } // TODO: Store a better reference to static meshes (rather than querying the world every step). var world = Parent.Scene.World; var map = world.RigidBodies.First(b => b.Shape is TriangleMeshShape); var normal = ground.Normal; var offset = PhysicsConstants.StepThreshold * RaycastMultiplier; // TODO: Use properties or a constant for the raycast length (and offset). // TODO: Sometimes downward step snapping doesn't work. Should be fixed. // The raycast needs to be offset enough to catch steps. if (PhysicsUtilities.Raycast(world, map, p + normal * offset, -normal, offset * 2, out var results) && results.Triangle != null) { // This means the actor moved to another triangle. var newGround = new SurfaceTriangle(results.Triangle, results.Normal, 0); // TODO: Is this projection needed? (since the position is already known from the raycast) newGround.Project(results.Position, out result); body.Position = (result + halfHeight).ToJVector(); Parent.OnGroundTransition(newGround); return; } // If the actor has moved past a surface triangle (without transitioning to another one), a very small // forgiveness distance is checked before signalling the actor to become airborne. This distance is small // enough to not be noticeable during gameplay, but protects against potential floating-point errors near // the seams of triangles. if (SurfaceTriangle.ComputeForgiveness(p, ground) > EdgeForgiveness) { Parent.BecomeAirborneFromLedge(); } }
// child the object to any valid object that it can be on and store what kind of object that is protected void AttachToTile() { Vector3 offset = PhysicsUtilities.OffsetToEdgeRenderer(GetComponent <SpriteRenderer>(), oppositeFacing); RaycastHit2D hit = Physics2D.Raycast(transform.position + offset, oppositeFacing.ToVector2(), 0.1f, canAttachToLayerMask); if (hit.collider != null) { transform.parent = hit.transform; parentLayer = LayerMask.LayerToName(hit.transform.gameObject.layer); } }
public override void PostStep(float step) { // This raycast distance is arbitrary. Should be short, but also long enough to catch transitions from // one wall triangle to another. const float RaycastLength = 0.5f; var player = (PlayerCharacter)Parent; var radius = player.CapsuleRadius; var body = Parent.ControllingBody; // The starting point of the raycast is pulled back by a small amount in order to increase stability // (without this offset, the player frequently clipped through walls). var p = body.Position.ToVec3() - flatNormal * (radius - 0.1f); if (PhysicsUtilities.Raycast(Parent.Scene.World, wallBody, p, -flatNormal, RaycastLength, out var results)) { // TODO: Might have to re-examine some of this if sliding along a pseudo-static body is allowed (such as the side of a sphere). // While sliding along the map mesh, the current triangle can change. if (wall != null) { var triangle = results.Triangle; // TODO: Verify that the new triangle isn't acute enough to cause a sideways collision instead. if (!wall.IsSame(triangle)) { wall = new SurfaceTriangle(triangle, results.Normal, 0, null, true); } } // Note that for meshes, the triangle (and its flat normal) might have changed here (due to the // condition above). var result = (results.Position + flatNormal * radius).ToJVector(); if (wall != null) { body.Position = (results.Position + flatNormal * radius).ToJVector(); } else { // TODO: Set orientation as well (for rotation platforms). body.SetPosition(result, step); } return; } // TODO: Consider adding edge forgiveness. // By this point, the player has moved off the current wall (without transitioning to a new triangle). player.BecomeAirborneFromWall(); }
// find out if the object is grounded bool isGrounded() { // for position, get the "bottom" edge in terms of the direction of gravity Vector2 position = (Vector2)transform.position + PhysicsUtilities.OffsetToEdgeRenderer(rend); //Debug.DrawLine(transform.position, position); float dist = 0.1f; RaycastHit2D hit = PhysicsUtilities.RaycastToGravity(position, dist, GameController.terrainLayer); if (hit.collider != null) { return(true); } return(false); }
private void SetEngineParameters() { float speed = 0; PhysicsUtilities.ScaleValueWithSpeed(ref speed, 0, 1, Handling.RB, Handling.MaxSpeed); Engine.SetParameter("Speed", speed); Engine.SetParameter("Force", Handling.ThrustInput); if (Handling.IsCarving) { float driftAmount = Mathf.Clamp(Mathf.Abs(Handling.TurnInput), 0.4f, 1.0f); Engine.SetParameter("Drift", driftAmount); } }
public void Place(Vector3 targetPosition, Quaternion rotation, LayerMask groundLayers, Transform parent = null, bool onGround = false) { transform.parent = parent; if (!onGround) { transform.position = targetPosition; } else { transform.position = PhysicsUtilities.FindPointOnGround(targetPosition, groundLayers); } transform.rotation = rotation; this.gameObject.SetActive(true); }
private void UpdateSpeedGauge() { float fill = SpeedGaugeImage.fillAmount; PhysicsUtilities.ScaleValueWithSpeed(ref fill, 0, 1, Handling.RB, Handling.MaxSpeed); SpeedGaugeImage.fillAmount = fill; SpeedGaugeImage.material.SetFloat("_GlowIntensity", fill); if (Handling.IsDashing) { SpeedGaugeImage.material.SetColor("_HDRColor", DashColor); } else { SpeedGaugeImage.material.SetColor("_HDRColor", DefaultColor); } }
void FixedUpdate() { _isColliding = false; // reset isColliding // if we're moving gravity and not grounded if (gravEnabled && (GameController.gravTransitionState || !_grounded)) { _rb.isKinematic = false; // we are now a dynamic rigidbody again PhysicsUtilities.ApplyGravity(_rb); } else { _rb.isKinematic = true; // set rigidbody to kinematic to prevent physics when not in motion _rb.velocity = Vector2.zero; // freeze the object } _grounded = isGrounded(); }
public virtual bool Shoot() { if (reloadTimer.timeRemaining <= 0) { reloadTimer.Reset(); reloadTimer.Start(); if (bulletPrefab != null) { Bullet bullet = ObjectPool.instance.SpawnComponent <Bullet>(bulletPrefab.prefabIndex, shootTrs.position, shootTrs.rotation); Vector3 velocity = PhysicsUtilities.GetVelocity(previousShootTrsPosition, shootTrs.position, deltaTime); Vector3 angularVelocity = PhysicsUtilities.GetAngularVelocity(previousShootTrsRotation, shootTrs.rotation, deltaTime); bullet.rigid.velocity = shootTrs.forward * shootSpeed + PhysicsUtilities.GetPointVelocity(velocity, angularVelocity, Vector3.zero); Physics.IgnoreCollision(bullet.collider, collider, true); bullet.shootingGun = this; bullet.collider.enabled = true; } return(true); } return(false); }
/// <summary> /// Performs the collision detection method used in the "Corner Alignment" feature. /// </summary> CornerAlignmentResult CornerAlignCollisions(bool positiveDirection, float cornerDetectionDistance, LayerMask layerMask) { CornerAlignmentResult result = new CornerAlignmentResult(); result.Reset(); CollisionHitInfo hitInfo = new CollisionHitInfo(); hitInfo.Reset(); if (cornerDetectionDistance < 0) { return(result); } float castDistance = characterBody.SkinWidth + cornerDetectionDistance; Vector2 rayOrigin = characterController2D.transform.position + (positiveDirection ? -1 : 1) * characterController2D.transform.right * characterBody.verticalArea / 2 - characterController2D.transform.up * characterBody.SkinWidth; hitInfo = PhysicsUtilities.Raycast( characterBody.Is3D(), rayOrigin, (positiveDirection ? -1 : 1) * characterController2D.transform.right, castDistance, layerMask ); if (hitInfo.collision) { result.point = hitInfo.point; result.normalRotation = Quaternion.LookRotation(characterBody.bodyTransform.Forward, hitInfo.normal); result.success = true; } return(result); }
// adjust the size of the laser depending on objects in the way void AdjustLaserDistance() { // escape if we don't have a laser child if (_laserChild == null) { return; } // check for any object that's not an ActiveAttachable RaycastHit2D hit = Physics2D.Raycast(_laserChild.transform.position, facing.ToVector2(), Mathf.Infinity, ~layerMask); if (hit.collider != null) { // calculate where the laser will stop based off the offset edge of the object we hit Vector2 endpoint = (Vector2)hit.collider.gameObject.transform.position + PhysicsUtilities.OffsetToEdgeCollider2D(hit.collider, oppositeFacing); // distance between the gun beginning of the laser and the endpoint float dist = Mathf.Sqrt(Mathf.Pow(_laserChild.transform.position.x - endpoint.x, 2) + Mathf.Pow(_laserChild.transform.position.y - endpoint.y, 2)); // set localScale of the laser - always in y because of how parent-child works on transforms in Unity _laserChild.transform.localScale = new Vector3(laserSizeX, dist, 0); } }
// check if we're grounded bool isGrounded() { Vector2 position = _groundChecker.position; // get our groundChecker object float dist = 0.1f; // how far are we checking // check both ends and the center of the game object RaycastHit2D[] hits = new RaycastHit2D[] { PhysicsUtilities.RaycastToGravity(position - new Vector2(_rend.bounds.size.x / 2f, 0), dist, GameController.terrainLayer), PhysicsUtilities.RaycastToGravity(position, dist, GameController.terrainLayer), PhysicsUtilities.RaycastToGravity(position + new Vector2(_rend.bounds.size.x / 2f, 0), dist, GameController.terrainLayer) }; foreach (RaycastHit2D hit in hits) { if (hit.collider != null) { GameController.gravTransitionState = false; // if we hit ground, we're not in GameController.gravTransitionState return(true); } } return(false); }
void FixedUpdate() { if (gravEnabled) { PhysicsUtilities.ApplyGravity(_rb); } else { _rb.velocity = Vector2.zero; } // only check for Grounded if we didn't override it with the idle check if (!_idleOverride) { grounded = isGrounded(); } // Do the following to resolve any times colliders hit, and the raycasts fail // if we do so, override the normal grounded check Vector3 currentPos = transform.position; _idleCheck += Time.deltaTime; if ((!grounded || GameController.gravTransitionState) && _idleCheck >= .25f && currentPos == _lastPos) { //Debug.Log("In idle check"); grounded = true; GameController.gravTransitionState = false; _idleCheck = 0; _idleOverride = true; } _lastPos = currentPos; //Debug.Log("grounded: " + grounded); //Debug.Log("gravTrans: " + GameController.gravTransitionState); HandleInput(); }
public static void ToggleEditorPhysicsSelected() { PhysicsUtilities.ToggleEditorPhysicsSelected(); }
/// <summary> /// Gets the velocity of the given point using values retrieved directly from the rigidbody. /// </summary> public VelocityData GetCurrentVelocityData(Vector3 point) { return(new VelocityData(CurrentVelocity, PhysicsUtilities.CalculateTangentialVelocity(point, CurrentAngularVelocity, CurrentWorldCenterOfMass))); }
private void ScaleXOffsetWithSpeed() { PhysicsUtilities.ScaleValueWithSpeed(ref XSpeedMultiplier, 0, 1, RB, Handling.MaxSpeed); }
private void ScaleZOffsetWithSpeed() { PhysicsUtilities.ScaleValueWithSpeed(ref ZOffset, 0, MaxZOffset, RB, Handling.MaxSpeed); }
void SpawnObject(Vector3 position, Vector3 normal) { if (rootContainer != null) { UndoTransformInRoot(); } // Get selected gameobject List <SpawnableObject> objs = spawnableObjects.FindAll( delegate(SpawnableObject s) { return(s.spawn == true); }); if (objs.Count == 0) { return; } int rndObj = UnityEngine.Random.Range(0, objs.Count); SpawnableObject selectedObject = objs[rndObj]; Vector3 positionUp = position; if (objGlobalSettings.spawn) { positionUp.y = positionUp.y + objGlobalSettings.offset; } else { positionUp.y = positionUp.y + selectedObject.offset; } GameObject newObj = Instantiate(selectedObject.prefab, positionUp, Quaternion.identity); // Apply random factors if (objGlobalSettings.spawn) { SpawnableObject.ApplyRandomFactors(objGlobalSettings, newObj.transform); } else { SpawnableObject.ApplyRandomFactors(selectedObject, newObj.transform); } // We add a box collider if no box collider is present. if (newObj.GetComponent <Collider>() == null && PhysicsUtilities.physicsScatter) { newObj.AddComponent <BoxCollider>(); } // If a collider is present and is a meshCollider, we have the problem that mesh colliders are not supported anymore. However, sometime when convex is set to true and error is thrown and convex fails. If we inflate the Mesh first, // the convex mesh is created correctly. if (newObj.GetComponent <MeshCollider>() != null && PhysicsUtilities.physicsScatter && newObj.GetComponent <MeshCollider>().convex == false) { newObj.GetComponent <MeshCollider>().inflateMesh = true; newObj.GetComponent <MeshCollider>().convex = true; } // We add a rigidbody if not present if (newObj.GetComponent <Rigidbody>() == null && PhysicsUtilities.physicsScatter) { newObj.AddComponent <Rigidbody>(); } // If there is a rigidbody, and is kinematic, we set kinematic to false. if (newObj.GetComponent <Rigidbody>() != null && PhysicsUtilities.physicsScatter && newObj.GetComponent <Rigidbody>().isKinematic == true) { newObj.GetComponent <Rigidbody>().isKinematic = false; } if (newObj.GetComponent <Rigidbody>() != null && PhysicsUtilities.physicsScatter == false) { DestroyImmediate(newObj.GetComponent <Rigidbody>()); } newObj.transform.parent = returnOrCreateRootContainer().transform; Undo.RegisterCreatedObjectUndo(newObj, "Physics Scatter : new objectS"); PhysicsUtilities.ActivatePhysics(); }
private void ScaleTurnForceWithSpeedInverse() { PhysicsUtilities.ScaleValueWithSpeedInverse(ref TurnForce, TurnForceMin, TurnForceMax, RB, Handling.MaxSpeed); }