Help on Conveyer Belt?

I needed to make a conveyor belt, so I followed a tutorial on how to do it. Once I implemented the code and put it into Unity, instead of the conveyer belt actually working, it starts drifting away.

My Conveyer belt has a rigidbody that Kinematic but has no gravity

My First Person Controller(which is the thing that is supposed to move in the conveyer belt) also has a rigidbody which is not Kinematic but has gravity

ConveyerBelt.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ConveyerBelt : MonoBehaviour
{
    public Rigidbody rb;

    public float speed = 10f;

    public Vector3 direction;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        GetComponent<Rigidbody>().position -= transform.forward * speed * Time.deltaTime;
        GetComponent<Rigidbody>().MovePosition(GetComponent<Rigidbody>().position + transform.forward * speed * Time.deltaTime);
    }
}

What is meant to do? From the two lines it looks like you are changing the position of the object, is it just not stopping?

Well according to the tutorial, both GetComponent().position GetComponent is supposed to make anything on the gameObject move towards a certain direction but not the gameObject itself.

Are you using this tutorial? Easy Conveyor Belt Physics in Unity

What you’ve got looks like a common way of implementing conveyors, except that you’re running those code in Update instead of FixedUpdate. I’m not certain that’s the issue, but that’s the first thing I’d change.

Your conveyor belt sets its own position. Which makes no sense.
You need to get the item(s) ON the belt and move those instead.

Edit: I’m wrong, this is seemingly (one) correct (way) for physics based conveyors.

The first thing you should do is take those GetComponent calls out of Update. You’re completely killing your game’s performance - these calls are extremely expensive. Use the rb variable instead and move the code to FixedUpdate.

It might look like that, but that’s not what happens in practice. I use basically the same approach for conveyors. You change the position of the conveyor in one direction by setting the transform position, then immediately MovePosition to put it back where it was at the start of the frame. The ultimate effect is that the conveyor doesn’t actually have any net movement, but any objects touching it will be moved along.

I suspect the issue is that this only works properly in FixedUpdate and not in Update.

2 Likes

Yeah, I just confirmed that I can break my conveyors in the way the OP is referring to by putting that code in Update instead of FixedUpdate. So, @BoxTraininc , put that code in FixedUpdate.

And, do what others have mentioned, and don’t use GetComponent like that, especially since you already have public Rigidbody rb; in a class variable.

2 Likes

I would add force at point, but with respect to mass and friction.

Well that fixed the Conveyer belt from drifting away, but it’s still not forcing my player to move. I suspect that it has something to do with the components of the player:

My player is a gameobject containing a model, a main camera and a gun prefab. The gameobject has a Character Controller, a Player movement script, a going up a ladder script and a Rigidbody with Gravity and Kinematics on.

In no part of the tutorial that it said what components should your object should contain(the one that you want to move), well at least none that I know of.

Have you tried putting the rigidbody to dynamic? If it’s set to kinematic collisions shouldn’t even affect the rigidbody anymore.

If you’re talking about “Continuous Dynamic”, then yes I did, but nothing really changed.
Just to double check, all I had to do was switch GetComponent with rb and turn the void to FixedUpdate, right?

The way that conveyor works, it will only move rigidbodies where IsKinematic is off/false. If your character controller needs to have IsKinematic enabled, then you’ll need to use a different approach to get the conveyor to move those kinds of objects. Something more along the lines of what others have already mentioned, where you probably need to call MovePosition on the character’s rigidbody while they’re standing on the conveyor. This probably isn’t too difficult, and there are various approaches you might take here. But I’m also not sure whether they’d be compatible with your character controller.

My Character controller is from a tutorial of Brackeys(Who is a great YouTuber by the ways) and nowhere in the tutorial it said to add a Rigidbody. I added a Rigidbody because I thought I needed one. So you’re saying that if I turn off Kinematic on my Player Rigidbody, it should work?

Well, if you did that, the conveyor belt would probably move the player. But I wouldn’t be very confident that your character controller would work anymore. If the character controller isn’t designed for non-kinematic rigidbodies, adding a rigidbody can easily break it.

Ultimately, you probably want one of the two pairings:

  • Find a Rigidbody Character controller that uses a non-kinematic rigidbody, then I’d expect that to work with the conveyors.
  • If you use a different kind of character controller, you’ll need to write some custom code to make it interact with the conveyor properly. Probably something that ties in with a Ground Test behavior to detect you’re standing on a conveyor, and manually move the player each frame in that case.

Well, looking back at my code, it turns out I was mistaken. I do indeed need a Rigidbody with Kinematics on, in order for the player to climb ladders. I’ve tried turning Kinematics of and putting my player on the Conveyer belt but to no avail

D’you think it might work if I were to add a function in the Character Controller Script telling it to move Backwards a bit if it collides with the Conveyer Hitbox?

Something like that would probably work. It feels a bit sloppy, but I imagine it would get the job done. If I were trying to do this quickly, I’d do it something like this. Note that this isn’t code, it’s just a rough approach:

  • Use a Raycast to test for the kind of surface you’re standing on. Your character controller is probably already doing something like this to see if it’s allowed to jump. (Grounded Tests are common in character controllers.)
  • See if the tag of the surface you hit is “ConveyorBelt”. This assumes you assign a tag of ConveyorBelt to your conveyor belt collider.
  • If the tag is “ConveyorBelt”, then on the RaycastHit call something like var conveyorController = raycastHit.collider.gameObject.GetComponent<ConveyorBeltController>();. This assumes the controller script for the conveyor belt is on the same object as the collider. If not, you might need to use GetComponentInParent to walk up from the collider to the parent.
  • Now that you have ‘conveyorController’, you can ask it things like its speed and direction. With that information, you can apply some movement to the character’s rigidbody.

On second thought, I don’t really want to take the “lazy” way out of things, so I’m just going to dismiss that idea. I’ll try to tweak the ladder script in order to make it not dependent on the players rigidbody