I am trying to bounce the tile above the circle on top of the platform, there is no problem when the platform is fixed, but when the script who make the platform move is activated, the tile crash the circle.
This is the script for moving the platform:
using UnityEngine;
using System.Collections;
public class PlatformMoveH : MonoBehaviour {
public float min;
public float max;
public float speed;
public float sens;
void Start(){
sens *= speed;
}
void Update () {
if (transform.localPosition.x > max) {
sens = -speed;
} else if (transform.localPosition.x < min){
sens = speed;
}
transform.Translate (sens * Time.deltaTime, 0, 0);
}
}
i can't add pictures here but in unity answers you can understand the problem better with pictures
http://answers.unity3d.com/questions/1009619/collider2d-and-translate-problem.html
i have no idea what is the problem.
can anyone help me please
You have to add a kinematic Rigidbody2D to your moving colliders. Colliders without a rigidbody are treated as static colliders by Unity and should never be moved.
From the official documentation:
The physics engine assumes that static colliders never move or change and can make useful optimizations based on this assumption. Consequently, static colliders should not be disabled/enabled, moved or scaled during gameplay. If you do change a static collider then this will result in extra internal recomputation by the physics engine which causes a major drop in performance. Worse still, the changes can sometimes leave the collider in an undefined state that produces erroneous physics calculations. For example a raycast against an altered Static Collider could fail to detect it, or detect it at a random position in space.
Related
I recently posted a problem with a jittering Camera Follow in my 2D Game made in Unity, which was solved here.
However after some time I noticed, that I am still getting jumps. I now know, that the problem lies in the lerp method of my camera follow. Time.deltaTime varies as described in my prior question and thus makes the player move different distances each frame. But because the camera reacts with a delay, you can see the jump on screen (on device even more than in Unity Editor).
A solution would be to detect those Time.DeltaTime jumps and in these cases make the camera imitate that jump somehow, am I correct? What would be a Workaround here?
These are my scripts:
public class Player: MonoBehaviour
{
float speed = 5f;
void Update()
{
transform.Translate(0,speed*Time.deltaTime,0);
}
}
public class CamFollow : MonoBehaviour
{
public Transform Player;
private Vector3 FollowVector;
float transition = 0.05f;
void LateUpdate()
{
FollowVector = Player.position - new Vector3(0, -4.0f, 10);
transform.position = Vector3.Lerp(transform.position, FollowVector, transition);
}
}
Try using Time.fixedDeltaTime. This is like deltatime but it's fixed and so it doesn't very as you said. It does reduce the jittering, but I would recommend using Cinemachine, as it's very performant and you would have a lot of control over it.
I have a rectangle player sprite with a Box Collider 2D and a Rigidbody2D attached. I also have a script for point-and-click movement attached to the player object (i.e. player moves to mouse click position). However as soon as the player character hits a collider, it starts to jitter rather than just fully stop. I don't know a lot about Unity physics other than what I've picked up in a few tutorials, so I'll include as much relevant information as I can.
The Rigidbody 2D component has all forces set to 0, except for mass being 0.0001. The body type is dynamic, and collision detection is set to continuous. My movement script looks like this, got it straight from a tutorial:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControls : MonoBehaviour
{
public float speed = 1;
private Vector3 target;
void Start()
{
target = transform.position;
}
void Update()
{
if (Input.GetMouseButtonDown(0)) {
target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
target.z = transform.position.z;
}
transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
}
}
Is there an easier way to implement smooth point-and-click movement?
I am developing a VR game.
Is a fighting game, the player will be able the punch the enemies (on his fist will be a collider and a disabled object with the damage script).
I need a script that will activate another object (the one with damage script) - (placed on his fist) but just on certain speed or force (you know, like in real life- if the enemy will be touched with the hand he should not be damaged, just on high force or speed)
What is the best solution?
thank you!
Since your player's fist is not being controlled by the physics system, it will not be possible to read the velocity of the player's hand like you would a normal Rigidbody. That being said, you can still calculate the speed and handle all of what you wish to do in one script.
Here's an example:
[RequireComponent(typeof(DamageScript))]
public class HandSpeedMonitor : Monobehaviour
{
public float threshold;
DamageScript damageScript;
Vector3 lastPos;
public void Awake()
{
damageScript = this.GetComponent<DamageScript>();
}
public void Start()
{
lastPos = this.transform.position;
}
public void Update()
{
float velocity = (lastPos - this.transform.position).magnitude / Time.deltaTime;
if(!damageScript.enabled && velocity > threshold)
damageScript.enabled = true;
else if(damageScript.enabled)
damageScript.enabled = false;
}
}
However, since .magnitude is an expensive call, you may want to consider storing your "threshold" as a squared speed "sqrThreshold" and use .sqrMagnitude, since it removes the square root component of vector math (saving on processing).
I want to make a pong game but my ball isn't flying like I want. My ball is getting impacted from gravity. I know i need to set the body type from dynamic to kinematic but if I use kinematic, my ball isnt moving anymore because my ball flys with addforce. Which force can I use so that I can kinematic use?
public class BallPhysics : MonoBehaviour {
public Rigidbody2D rbBall;
public float SpeedX = 10.0f;
public float SpeedY = 5.0f;
void FixedUpdate()
{
rbBall.AddForce(new Vector2(SpeedX, SpeedY)); // my ball is flying
}
void OnCollisionEnter2D(Collision2D collisionInfo) // collision for the walls
{
if (collisionInfo.collider.tag == "wall")
{
SpeedX = -SpeedX;
SpeedY = -SpeedY;
}
}
}
There is no useGravity in RigidBody2D but you can simply leave IsKinematic disabled and rather also disable it's gravityScale
private void Start()
{
rbBall.gravityScale = 0;
}
this has the same effect as disabling useGravity on a RigidBody. Especially in the context of your question I really like the note
it may be easier to implement a flying character by turning off its gravity rather than simulating the forces that keep it aloft.
;)
or alternatively disable gravity for the entire scene/project using Physics2D.gravity
private void Start()
{
Physics2D.gravity = Vector2.zero;
}
To the question itself
Is there an alternative for addforce if I want use kinematic?
No and yes...
From RigidBody2D.isKinematic
Should this rigidbody be taken out of physics control?
If this property is set to true then the rigidbody will stop reacting to collisions and applied forces. This can be useful when an object should usually be controlled "kinematically" (ie, non-physically) but then sometimes needs physics for realism. For example, a human character is usually not implemented using physics but may sometimes be thrown through the air and collide with objects as the result of an impact or explosion.
Or also from Rigidbody.isKinematic
If isKinematic is enabled, Forces, collisions or joints will not affect the rigidbody anymore. The rigidbody will be under full control of animation or script control by changing transform.position.
So simply use the
transform.position = ...
as usual.
For having something similar to AddForce you could store a local speed vector and add more speed like
// public so you can also configure
// it in the inspector or set it from another script
public Vector2 speed;
public void AddForce(Vector2 force)
{
speed += force;
}
private void Update()
{
transform.position += speed * Time.deltaTime;
}
However in your case you don't want to add speed each frame but probably only set a certain speed once at start and on collisions.
Im currently developing an Air hockey game in Unity3d. The issue I'm having is that when the player attempts to hit the puck too quickly, the player ends up going through the puck and therefore there is no collision. The game works perfectly as expected if the player stays still and the puck hits the player or if the player hits the puck at a slow pace.
The player has a rigidbody using continuous collision detection using a capsule collider. The puck also has rigidbody with continuous dynamic collision detection and a mesh collider with convex.
I tried setting the fixed timestep to 0.01 but that didn't have an effect. Here is the script for the player movement:
void ObjectFollowCursor()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Vector3 point = ray.origin + (ray.direction * distance);
Vector3 temp = point;
temp.y = 0.2f; // limits player on y axis
cursorObject.position = temp;
}
and here is the code for the puck when it collides with the player:
// If puck hits player
if(collision.gameObject.tag == "Player")
{
Vector3 forceVec = this.GetComponent<Rigidbody>().velocity.normalized * hitForce;
rb.AddForce(forceVec, ForceMode.Impulse);
Debug.Log ("Player Hit");
}
Any help would be much appreciated. Thanks.
The problem you are having its called "tunneling".
This happens because your object is moving at a high speed and in that specific frame the collision is not detected. In frame n the ball is just in front of the bat, but when frame n+1 is calculated the ball has moved behind the bat, thus "missing" the collision completely.
It is a common problem but there are solutions.
I recommend you study this script and try to implement on your game.
This is not my code:
SOURCE: http://wiki.unity3d.com/index.php?title=DontGoThroughThings
using UnityEngine;
using System.Collections;
public class DontGoThroughThings : MonoBehaviour
{
// Careful when setting this to true - it might cause double
// events to be fired - but it won't pass through the trigger
public bool sendTriggerMessage = false;
public LayerMask layerMask = -1; //make sure we aren't in this layer
public float skinWidth = 0.1f; //probably doesn't need to be changed
private float minimumExtent;
private float partialExtent;
private float sqrMinimumExtent;
private Vector3 previousPosition;
private Rigidbody myRigidbody;
private Collider myCollider;
//initialize values
void Start()
{
myRigidbody = GetComponent<Rigidbody>();
myCollider = GetComponent<Collider>();
previousPosition = myRigidbody.position;
minimumExtent = Mathf.Min(Mathf.Min(myCollider.bounds.extents.x, myCollider.bounds.extents.y), myCollider.bounds.extents.z);
partialExtent = minimumExtent * (1.0f - skinWidth);
sqrMinimumExtent = minimumExtent * minimumExtent;
}
void FixedUpdate()
{
//have we moved more than our minimum extent?
Vector3 movementThisStep = myRigidbody.position - previousPosition;
float movementSqrMagnitude = movementThisStep.sqrMagnitude;
if (movementSqrMagnitude > sqrMinimumExtent)
{
float movementMagnitude = Mathf.Sqrt(movementSqrMagnitude);
RaycastHit hitInfo;
//check for obstructions we might have missed
if (Physics.Raycast(previousPosition, movementThisStep, out hitInfo, movementMagnitude, layerMask.value))
{
if (!hitInfo.collider)
return;
if (hitInfo.collider.isTrigger)
hitInfo.collider.SendMessage("OnTriggerEnter", myCollider);
if (!hitInfo.collider.isTrigger)
myRigidbody.position = hitInfo.point - (movementThisStep / movementMagnitude) * partialExtent;
}
}
previousPosition = myRigidbody.position;
}
}
You were right to try continuous collision detection (CCD). There are some constraints (especially in this case where you want to use CCD with two moving objects rather than one moving object and one static object), but it is designed for this kind of scenario. The Rigidbody documentation goes into these constraints:
Set the collision detection mode to Continuous to prevent the
rigidbody from passing through any static (ie, non-rigidbody)
MeshColliders. Set it to Continuous Dynamic to also prevent the
rigidbody from passing through any other supported rigidbodies with
collision detection mode set to Continuous or Continuous Dynamic.
Continuous collision detection is supported for Box-, Sphere- and
CapsuleColliders.
To sum up, both puck and paddle need to be set to Continuous Dynamic, and both need to be Box-, Sphere-, or Capsule Colliders. If you can make these constraints work for your game you should be able to get continuous collision detection without writing it yourself.
A note about Unity's CCD that bears repeating:
Note that continuous collision detection is intended as a safety net
to catch collisions in cases where objects would otherwise pass
through each other, but will not deliver physically accurate collision
results, so you might still consider decreasing the fixed Time step
value in the TimeManager inspector to make the simulation more
precise, if you run into problems with fast moving objects.
But since you are manually specifying the collision reaction, that might not be an issue.