Or making them bounce when colliding. but now it's not detecting any collision.
The first cube have a Rigidbody Use Gravity and Is Kinematic both checked enabled true.
If I will disable the Is Kinematic the cube will fall down.
Both cubes have attached the same script.
Both cubes have a box collider and the Is Trigger on both is unchecked disabled.
This script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Door : MonoBehaviour
{
public Transform target;
public float speed;
private void Start()
{
}
private void Update()
{
float step = speed * Time.deltaTime; // calculate distance to move
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
}
Each cube have the script and target is the other cube. So both cubes are moving to each other but never collide.
Both cubes settings screenshot :
It would be better practice set rigidbody.velocity once instead of changing transform.position every frame, but this solution should work regardless:
private bool collided = false;
private void Move() {
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
private void Update() {
if (!collided) {
Move();
}
}
private void OnCollisionEnter(Collider other) {
if (other.gameObject.GetComponent<Door>() != null) {
collided = true;
}
}
This may not be the best way to do it depending on how you plan on moving forward, but this is a way that works.
If you want to make them bounce, I'd suggest using rigidbody.AddForce() or set rigidbody.velocity. Then you can either use a bouncy physic material or changing the OnCollisionEnter code to use rigidbody.AddForce() or rigidbody.velocity when they collide with each other.
Related
My movement is working fine without Time.deltaTime but when I add it to my player movement I can move left to right fine but I fall slowly and I cant jump
using Newtonsoft.Json.Bson;
using System;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PlayerMovement : MonoBehaviour
{
[SerializeField] private float horSpeed;
[SerializeField] private float vertSpeed;
private Rigidbody2D rb;
private Boolean isJumping;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
// we store the initial velocity, which is a struct.
var v = rb.velocity * Time.deltaTime;
if (Input.GetKey(KeyCode.Space) && !isJumping)
{
vf.y = vertSpeed;
isJumping = true;
}
if (Input.GetKey(KeyCode.A))
{
vf.x = -horSpeed;
}
if (Input.GetKey(KeyCode.D))
{
vf.x = horSpeed;
}
if (Input.GetKey(KeyCode.S))
{
vf.y = -vertSpeed;
}
rb.velocity = vf;
if(Input.GetKey(KeyCode.Escape))
SceneManager.LoadScene(0);
}
private void OnCollisionEnter2D(Collision2D collision)
{
isJumping = false;
}
}
I've added it to my enemy script and it works fine so im not sure whats different with player movement to using transform.position
Why would you multiply the velocity by Time.deltaTime?
This is used to convert a value from a "certain unit per frame" into a value "certain unit per second".
A velocity already IS a value in units per second.
Linear velocity of the Rigidbody in units per second.
=> It makes no sense to apply Time.deltaTime here at all.
For your X axis movement it doesn't make much difference since you anyway apply that velocity continuously every frame. Here you just would probably want to handle the case where neither left nor right is pressed and set vf.x = 0.
For the Y axis however you apply the jump only once, just to divide it by about 60 (or whatever your frame rate is) right in the next frame => you never give it the chance to fall or jump.
In general you should modify the Rigidbody in FixedUpdate. In your specific case it is fine to do this in Update, it is just redundant work ;)
I need some help with Unity.
I try to make an object to detect a collision, but for some reason, the OnColissionEnter function is not called.
Both my objects have rigidBody and Box Collider attached, isTrigger is unenabled as well.
I supposed it's because I have AddForce in my code, but I am not sure. Have anybody a clue what is going wrong there?
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cuplat2 : MonoBehaviour
{
public Vector3 Target = new Vector3();
private Rigidbody rb;
public float thrust;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
Vector3 NewPosition = transform.position + Target;
Vector3 Position = transform.position;
if (transform.position.x < Target.x)
{
rb.AddForce(transform.position * thrust);
}
else
{
//rb.isKinematic = true;
}
}
public void OnCollisionEnter(Collision collision)
{
Debug.Log("stop");
if (collision.gameObject.name == "Cupla T2")
{
Debug.Log("stop");
}
}
}
One of your rigidbodies has to have isKinematic = false;
If it's not possible in your case I see they have workaround for that:
https://forum.unity.com/threads/collision-detection-for-kinematic-rigidbodies.885778/
Other option would be that the collision is disabled in collision layer mask, but that would cause objects to pass trough each other (I believe that's not the case)
Third option: your rigidbody does not have collider (maybe collider is on parent, has enabled = false, or inactive game object?)
Fourth option: If your object moves very fast you should change Collision Detection Mode to Continous Dynamic
How about the collision layer matrix? Go into Edit > Project Settings, then select the Physics. Check if the layers set to the GameObjects are actually having any collision between them. Collision Layer matrix
Sorry for the bad formatting I don't know how to do this. I'm using 2020.3.21f1 and following a tutorial and when the enemy circle hits the player he doesn't take damage. when they collide they don't overlap at all, but the Debug.log isn't registering either so I think that the circle collider 2D is the problem. the enemy sprite still moves towards the player when it is in range. another problem (that will turn into a feature if I cant figure out how to change it) is that when the enemy collides with the player and the player pushes it goes the direction it was pushed until it runs into something Here's the tutorial I'm following
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy: MonoBehaviour
{
public float speed = 3f;
private Transform target;
[SerializeField] private float attackDamage = -10f;
private void Update(){
if (target != null){
float step = speed*Time.deltaTime;
transform.position = Vector2.MoveTowards(transform.position, target.position, step);
}
}
private void OnCollision(Collision2D other){
if (other.gameObject.tag == "player"){
Debug.Log("hit");
other.gameObject.GetComponent<PlayerHealth>().UpdateHealth(attackDamage);
}
}
private void OnTriggerEnter2D(Collider2D other) {
if(other.gameObject.tag == "Player"){
target = other.transform;
Debug.Log(target);
}
}
private void OnTriggerExit2D(Collider2D other) {
if(other.gameObject.tag == "Player"){
target = null;
Debug.Log(target);
}
}
}
The sprite by itself wont detect collision, you need to add a box collider for that. If you add that component to the player then modify your code to include those collision detections then it should function ad intended.:)
-TheHackintoshProgrammer;
I need to make a platform that moves up when the player enters it.
MovingPlatform.cs
public class MovingPlatform : MonoBehaviour
{
[SerializeField]
private Vector3 newPosition;
void Start()
{
newPosition = new Vector3(transform.position.x, transform.position.y + 5, transform.position.z);
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
transform.position = Vector3.MoveTowards(transform.position, newPosition, 4 * Time.deltaTime);
}
}
}
My problem is that the platform moves up only a little and without the player.
Why the platform moves only once
The reason, the platform moves only once is due to OnTriggerEnter getting called upon entering the trigger not staying inside it. If you want it to get called constantly, while inside it, use OnTriggerStay instead or assign a boolean value inside OnTriggerEnter and OnTriggerExit methods and change your position inside an Update/FixedUpdate.
Why the platform moves without the player
Regarding the platform moving without the player, I'm assuming that the player is a physics object and you expect them to be pushed by it. Potential reasons for that happening:
You are moving the platform too fast
You are moving the platform outside the physics loop
The platform and/or player doesn't have a collider (Trigger colliders do not collide)
Potential solution
It uses OnCollisionEnter instead of the OnTriggerEnter since it seemed to be more appropriate in this case (Make sure to have a non-trigger collider, if you gonna use it).
using UnityEngine;
public class MovingPlatform : MonoBehaviour
{
[SerializeField]
private Vector3 targetPosition = default;
private bool touchingPlayer = false;
private void Start()
{
targetPosition = new Vector3(
transform.position.x,
transform.position.y + 5f,
transform.position.z);
}
private void FixedUpdate()
{
if (touchingPlayer)
{
transform.position = Vector3.MoveTowards(
transform.position,
targetPosition,
4f * Time.fixedDeltaTime);
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Player"))
touchingPlayer = true;
}
private void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("Player"))
touchingPlayer = false;
}
}
https://streamable.com/mbevlw
Instead Of Moving the platform using Vector3s, Create an animation that plays when the player enters a trigger zone.
My game is a topdown zombie shooter and whenever the zombies get to the player they bunch up underneath them, to the point where the player can just walk over the zombies. I noticed that when I check isKinematic on the Rigidbody the zombies cant push the player up to go underneath him, so they just run into him(which is what I want). Despite this I am then unable to move. How can i fix this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMoving1 : MonoBehaviour {
public float moveSpeed;
private Rigidbody myRigidbody;
private Vector3 moveInput;
private Vector3 moveVelocity;
private Camera mainCamera;
public GunController theGun;
void Start () {
myRigidbody = GetComponent <Rigidbody>();
mainCamera = FindObjectOfType<Camera>();
}
// Update is called once per frame
void Update () {
moveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical"));
moveVelocity = moveInput * moveSpeed;
Ray cameraRay = mainCamera.ScreenPointToRay(Input.mousePosition);
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
float rayLength;
if(groundPlane.Raycast(cameraRay,out rayLength))
{
Vector3 pointToLook = cameraRay.GetPoint(rayLength);
transform.LookAt(new Vector3(pointToLook.x,transform.position.y,pointToLook.z));
}
if (Input.GetMouseButtonDown(0))
theGun.isFiring = true;
if (Input.GetMouseButtonUp(0))
theGun.isFiring = false;
}
void FixedUpdate(){
myRigidbody.velocity = moveVelocity;
}
}
With isKinematic == true You can't change object position through rigidbody, You can only change transform.position.
I think it could be better, if You set isKinematic to false and add stopping distance to enemies, so they can't get too close to player.
Being that your player can no longer be effected by the physics engine, you'd have to manipulate the object's transform manually. Your script isn't ideally setup for it currently, but if I was to hack it into it and try to make it work it would look something like this:
(you can change it from fixedUpdate to update if you're no longer utilizing the physics engine)
void update(){
float x = Input.GetAxisRaw("Horizontal")* Time.Deltatime;
float z = Input.GetAxisRaw("Vertical") * Time.Deltatime;
transform.position = new Vector3(transform.position.x+x,0,transform.position.z+z);
Another way of doing this is to lock the position of Y for the player (assuming Y is the positive "up" direction). isKinimatic is best when you want to move the player or objects around yourself.
I would say upping the mass is better in this case, and you can keep isKinematic unchecked in this case then too. Also apply the lock for Y movement (again if it is the "up" direction from the plane)
Let me know what your solution is regardless, I've had some issues in the past as well with these types of events happening