Is it possible to program a 2D sprite to move around a 3D environment?

So I’m in the starting phases of making a Racing game, and my goal for is to achieve a stylized, retro look straight out of the Golden age of Nintendo. Right now, I need to figure out how I can get my player character to navigate within the game world, yet the question I need to answer is how to do so. I’ve managed to have narrowed down games’ concept to its’ minimum viable product; the core gameplay revolves around the player character driving around the course, plus if optional the ability to change from one state to another.
In this case though, the player character is a 2D sprite, and the scene they have to navigate around is 3D space. sounds like a challenge right, but that doesn’t mean it’s impossible, I mean just look at the original paper mario for N64. the real question of course is how to do it.

Simple speaking, I want to enable my player character to navigate to navigate a three-dimensional environment, and for it to control like a race car. Basically, I’m hoping to develop a controller script for the player to behave and function like the go-karts from Super Mario Kart,

or possible like the single player cars from the NES title Rad Racer,

there’s no need for a reverse, the player just needs to be able to accelerate, turn, brake, and if desired drift. The question now is how to approach this. how should the character interact with the environment? should the character use a rigidbody, or be assigned a custom character controller? Because the character is 2d, will the player need wheelcolliders or not? If anyone out there reads this thread, please reply to this with some solid advice and opinions. In any case, doe’s anyone have any ideas what so ever?

Treat the game as if it were 3d. Only after all the logic of 3d racing, then you can adjust the main object to appear 2d.

Have the camera locked directly behind the 3d object (Make the camera the child of this object).

Put a capsule into the game with a Rigidbody and treat it as a 3d race car. Once everything else is complete, then put in the sprite on a plane and hide the mesh of the capsule. Since the camera is locked directly behind the camera you will never see that it is a plane.

Wow, that’s actually a whole lot of info there.

It’s all good though, this is pretty simple.

If you’re looking for retro style then use a box collider with a rigidbody. You don’t HAVE to use the in engine physics at all (and if you want retro, you’ll want your own), but if the object is moving you’ll want a rigidbody so that the Unity remembers that it moves and doesn’t have to re-open all the moving functions every frame. I would recommend turning the rigidbody into kinesmatic so it only does what you tell it to do, then use translate to move it, rather than addforce.

Next up, for the track you have two different methods there. Mario Kart uses a 2d plane and rotates it with Mode7 (a function specific to the SNES). While Rad Racer (I think it’s Rad Racer) is doing some tricks to make 2d sprites into a track. Long story short, go for the Mario Kart look. Just make a ground collider and cover it in 2d tiles for graphics. Or 3d ones, whatever.

For the graphics I would recommend 3d models, but if you’re set on 2d that’s fine. Make a parent that contains the collider and the controlling scripts. Then give it a child with a camera and another child with the graphics and a separate empty object named “mark” (I’ll explain).

Have the camera component offset from the center of the object and place the object in the dead center of the parent object (the one with the collider and RB on it).

Place the graphics in the middle of the parent as well.

Then with mark, place a script on the main object that tells the empty “mark” object to jump to their location at the start of the Update. And on the camera object tell it to look at mark on a lateupdate. With some tweaking, the result will be that the camera will look in the direction that you are moving (not facing!). You may also need to tell it to only look at if the mark if it does not have the same position, or within a parameter.

1 Like

There is no such thing called “Unity 2D”.
Everything in Unity is 3D, even sprites.
About sprites, the shader ignore depth but you can still move your sprite on the Z axis and It will change in size if you use a perspective camera.

I would indeed keep a 3D logic, just go for pixel art.

1 Like

Alright, so far I’ve set up a mock stage to represent the game environment thus far a basic setup of how the player starts up.


I’m using a simple plane right now with a terrain collider, along with some cubes with box colliders to act as obsticles. As for the player character, the basic set up is this.
2930125--216651--ex2.jpg
The parent labled simply “Car” has attached both a box collider, as well as a rigidbody set to in kinematic and gravity off. It’s children consist of the Main Camera(which is set at an x-rotation of 7.5, and a position offset of -2,10,0), An empty nicknamed as Mark, and a cube acting as the graphics for the player labled Car Mesh.
I’ve yet to set up scripts for anything as of right, since I would to figure out what kind of controller scripts I should to set up for the player Character. Should I make a 3rd person controller that behaves like a racecar( deals with things like velocity and so forth), or should go for a simple car controller set-up modified to work without wheelcolliders?

So recently, I’ve tried to create a script for my player model based on the work done for the Hover Car Practice livestream, minus the hovering of course, and though I work pretty well, It wasn’t exactly what I wanted. I mean car was able to move forward when the kinematic was turned off, it turns certainly well to, but the controllers wern’t were just terrible. What I want for my player to do is accelerate forward on the Z-axis, make turns horizontally, as well as be able to brake when needed and if desired drift whenever needed. much like a game of Mario Kart. anybody got some advice, questions, or opinions to give on this?

If you want a tweakable realistic car behavior, I use this https://www.assetstore.unity3d.com/en/#!/content/403 (worth the price and still working well in 5.5.0f3).

Otherwise I would code a fully simple behavior myself without using physic (to get full control of what’s happening).

Sorry I just saw this.

For some reason I got dropped from following the thread.

If you still want the camera to follow the car’s global movement (and not just which way it’s facing) you’re going to want to position the mark every frame where the car is positioned, move the car, then have the camera look away from the mark.

This means that the mark can not be a child of the car. If it’s a child, it will move with the car and lose where it’s supposed to be.

Basically, it means that I should make my camera to NOT look directly behind it, right?

Also, do you have any ideas when it come to the physics of the car, or know anyone who might have some insight. I have the car parent set up with a box collider as well as a rigidbody made into a kinematic with gravity turned off. I’ve also tried to apply what I’ve learn from the hovercar practice session( minus the hovering of course ), but when I tried to move my car it won’t even budge.

here’s a the video by the way in case it might help with anything

https://www.youtube.com/watch?v=476DIv7SPMQ

now I was wondering what I might have done wrong? and of course, what could I still improve on?

here’s the scripting I used for the Car object

using UnityEngine;
using System.Collections;

public class CarMotor : MonoBehaviour {

    public float speed = 90f;
    public float turnSpeed = 5f;
    private float powerInput;
    private float turnInput;
    private Rigidbody carRigidbody;


    void Awake ()
    {
        carRigidbody = GetComponent <Rigidbody>();
    }

    void Update ()
    {
        powerInput = Input.GetAxis ("Vertical");
        turnInput = Input.GetAxis ("Horizontal");
    }

    void FixedUpdate()
    {
        Ray ray = new Ray (transform.position, -transform.up);
        RaycastHit hit;

        carRigidbody.AddRelativeForce(0f, 0f, powerInput * speed);
        carRigidbody.AddRelativeTorque(0f, turnInput * turnSpeed, 0f);

    }
}

Basically I just use the hoverMotor script from the project and just cut out the bits involving hovering. Regardless, I was hoping it would still work as well. So again, what do you think I should do?

Kinematic means that the rigidbody ignores physics. It means that it does not do anything when a force is applied to it, such as with your script. And it means that it does not react to gravity.

I was saying that if you want to have physics more like the old school ones that you’ll need to make your own controls from the ground up with kinematic rigidbody.

But if you want to go for the hover car script, go for it. Just turn off kinematic.

As far as the camera goes I’m seeing that I was not as clear as I could have been.

For the camera make an empty. Then child a camera in the empty. Make sure the camera is dead center rotation (0,0,0). Then turn it complete around so it’s facing backwards. That way when the parent looks at the mark, the camera will be looking the opposite direction.

Also, move the child around in the parent to position where you want it. If you move the parent it will screw up the position.

Okay, I’ll try it out and look into what I can do with a Kinematic.

@Metalhawk93

Here is a few links that might help you here, I wanted to look at an outrun game a while back and found this.

Also look into the following, he goes though the projection part.

http://www.extentofthejam.com/pseudo/

if you do get an example working it would be nice to see it.

1 Like

might be of interest

1 Like

Any sources you guys know of that use C++ by chance though?

So here’s a status update, I’m starting to make some progress with my game, but I’ve come to a slight problem. So for my Car Object parent I’ve created and assigned a simple controller consisting of Input.GetAxis scripts,

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

public class CarController : MonoBehaviour {

    public float speed = 10.0f;
    public float rotationSpeed = 100.0f;
    void Update(){
        float translation = Input.GetAxis("Vertical") * speed;
        float rotation = Input.GetAxis("Horizontal") * rotationSpeed;
        translation *= Time.deltaTime;
        rotation *= Time.deltaTime;
        transform.Translate(0, 0, translation);
        transform.Rotate(0, rotation, 0);
    }
}

as well as a script I refer to as CameraFacingBillboard.

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

public class CameraBillboardControl : MonoBehaviour {

    public Camera m_Camera;
  
    void Update()
    {
        transform.LookAt(transform.position + m_Camera.transform.rotation * Vector3.forward,
            m_Camera.transform.rotation * Vector3.up);
    }
}

Now while both work well on there own separately, while both are on at the same time, it’s gets a little glitchy. When I move my carobject, it moves only the assigned cameras’ xyz axis, therefore causing to do some undesirable things. such as phasing through the floor for starters. So I was wondering, what might I be doing wrong here?

Also, what does anyone think I should add to my carcontroller script? be sure to give me a logical answer.

I havn’t really analyse your code but to me, you should not make your sprite facing the camera but scale it instead:
(15:00 - 17:43) how to do it rightly at 17:43

Okay so recently, I’ve been experimenting the scripting classes for billboard assets. So far I’ve made a simple script for the graphics child for my gameobject.

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

public class SpriteBilboard : MonoBehavior {

public BillboardAsset();
public float height;
public float width;
public int imageCount;
public void GetImageTexCoords(List<Vector2>ImageTexCoords);

}

Now in unity it doesn’t seem to run right. unity says that public BillboardAsset(); needs a return to work, same thing sorta applies to GetImageTexCoords as well. any ideas on what I’m doing wrong?

Seems normal to me.

public BillboardAsset(); is like writing:

public BillboardAsset MyFunction()
{
// without any return
}

Maybe you either want to do this

public class SpriteBilboard : MonoBehavior 
{
public BillboardAsset billboard;
public float height;
public float width;
public int imageCount;
public void GetImageTexCoords(List<Vector2>ImageTexCoords);

}

Or this

public class SpriteBilboard : BillboardAsset
{
public float height;
public float width;
public int imageCount;
public void GetImageTexCoords(List<Vector2>ImageTexCoords);

}

or even this ?

public class SpriteBilboard : MonoBehavior 
{

public BillboardAsset Billboard { get; set; }
public float height;
public float width;
public int imageCount;
public void GetImageTexCoords(List<Vector2>ImageTexCoords);

}

I’m Hoping one of these will work with the Billboard Asset.

okay, so I tried this code, and it says

public class SpriteBilboard : MonoBehavior
{
public BillboardAsset billboard;
public float height;
public float width;
public int imageCount;
public void GetImageTexCoords(List<Vector2>ImageTexCoords);
}

I’ve tried this code, and got another error that said the same thing still.

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

public class SpriteBilboard : MonoBehavior
{
    public BillboardAsset Billboard { get; set; }
    public float height;
    public float width;
    public int imageCount;
    public void GetImageTexCoords(List<Vector2>ImageTexCoords);
}

any idea what’s missing, or what might needs to be added on?