If anyone can tell me how to get a working ladder in my 2d side scroller that would be great. I have no idea where to start since this is my first time making a game, and, I just started making it 4 days ago.
The game looks 2d except for the character, but everything is made out of simple cubes.
Here is a video of how it looks:
I am testing the player controls with the Player Controller script in this video:
Hmm…Interesting. Well off the top of my head I would suggest you have box collider on the ladder IF possible and have a trigger happen on the player script / input manager when it comes near it. This way you can then trigger the up arrow to then allow the player to animate and move its position upwards so long as it is near the ladder. Also, what would be nice if the ladder itself would relay back to you the height of it, this way you can check if you are almost to the top and have the player animate to turn left or right. This way the player can actually get on solid ground rather then go up to the top, then fall again. Make sense?
It makes sense, but I just don’t know how to do the scripting myself just yet. I am currently learning how to do all of this coding stuff, but it’s only been 4 days…
Ah no worries dude, I got your back. First off, this script he has is great BUT its how would you say…not fully complete? Essentially it is not ideal to “hardcode” anything. You want to create a robust system where you can employment X amount of controls and feel confident you can port this on any system and feel like a champ. What I do is use a Singleton Paradigm in C# that I call InputManager that allows me to relay info to InputManager with delegates and events to trigger things. My Player script varies. For this situation you seem to have a basic JUMP, LEFT, RIGHT motion here am I right?
I used to be a tutor for Computer Science so I like to help people and you seem interested in programming so I am here to help. What I recommend is to create a structure for your inputs. The InputManager I was talking about can help you have a means of connecting your player to actions. By this I mean on your keyboard when you say hit LEFT the player should move to the left. When you hit a SPACE you expect it to lets say jump. For this, in no way shape or form should the player ever even check if anything has happen, so there should be NO update method for player for controllers EVER.
Like I said before it is ideal to use Object-Oriented Design patterns to help you in situations like these. So for this character there will be some things we have to take into consideration such as environments and so forth. Here is the singleton design pattern I was talking about that I can take you through (Implementing Singleton in C# | Microsoft Learn)
What I feel, and this is my opinion, is to have have a script for your individual controllers that then trigger an event that will then fire the player to move.
So for now, lets look at implementing our InputManager.cs
using UnityEngine;
using System.Collections;
public sealed class InputManager : MonoBehaviour {
private static readonly string _tag = "InputManager"; // This will be used to find the prefab in the game with a specific tag.
private static InputManager _instance; // This holds the reference to InputManager.
// This is a static property that returns the refernce to InputManager.
public static InputManager Instance {
// The 'get' keyword is an accesor
get {
// This 'if' statements check if the InputManager reference is null meaning if it exits or not.
if(InputManager._instance == null) {
// If the refernce, _instance, is null lets try to find it in the scene.
// This finds the game object we will create as a prefab that holds this script.
GameObject inputManager = GameObject.FindGameObjectWithTag(InputManager._tag);
// Now we check the game object if it is null or not if not, lets get the component of InputManager
if(inputManager != null) {
// This returns a reference to the compenent of InputManager and assigns it to _instance.
InputManager._instance = inputManager.GetComponent<InputManager>();
}
// Here we check if the _instance is still null, meaning have we still not found InputManager?
if(InputManager._instance == null) {
// If we have not, then we have to create and log an error letting the progammer know that InputManager is NOT in the scene and to fix it.
Debug.LogError(typeof(InputManager).ToString() + ": Could not find Game Object with Tag: " + InputManager._tag);
}
}
// FINALLY we return the reference.
return InputManager._instance;
}
}
}
So here I implemented the singleton design. This allows me to have a ways to connect to the InputManager that will then trigger events later, I will show you, that will have your player move and climb your ladder.
using UnityEngine;
using System.Collections;
public sealed class InputManager : MonoBehaviour {
private static readonly string _tag = "InputManager"; // This will be used to find the prefab in the game with a specific tag.
private static InputManager _instance; // This holds the reference to InputManager.
// This is a static property that returns the refernce to InputManager.
public static InputManager Instance {
// The 'get' keyword is an accesor
get {
// This 'if' statements check if the InputManager reference is null meaning if it exits or not.
if(InputManager._instance == null) {
// If the refernce, _instance, is null lets try to find it in the scene.
// This finds the game object we will create as a prefab that holds this script.
GameObject inputManager = GameObject.FindGameObjectWithTag(InputManager._tag);
// Now we check the game object if it is null or not if not, lets get the component of InputManager
if(inputManager != null) {
// This returns a reference to the compenent of InputManager and assigns it to _instance.
InputManager._instance = inputManager.GetComponent<InputManager>();
}
// Here we check if the _instance is still null, meaning have we still not found InputManager?
if(InputManager._instance == null) {
// If we have not, then we have to create and log an error letting the progammer know that InputManager is NOT in the scene and to fix it.
Debug.LogError(typeof(InputManager).ToString() + ": Could not find Game Object with Tag: " + InputManager._tag);
}
}
// FINALLY we return the reference.
return InputManager._instance;
}
}
public delegate void Action(MovementType direction, Vector3 movementVector = default(Vector3));
}
/// <summary>
/// Movement type.
/// </summary>
public enum MovementType {
NONE = 0,
MoveRight,
MoveLeft,
MoveForward
}
The next thing we want to do is create something that represents parameter list signatures and return types. This is known as a delegate. “A delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type. You can invoke (or call) the method through the delegate instance.” (Delegates - C# | Microsoft Learn). So of course we will add this to our InputManager
Yes, this way you can make your controllers for your game for the keyboard and later on implement it for touch too. By making it very generic and nothing hardcoded you can allow yourself to create extensive and reusable code for any situation with little changes to no changes.
Now that we have that we can now move on to create our trigger. Now in C# there is a type known as an event, this event is going to allow us to trigger the delegate by which any script can “register” to it. “An event is a message sent by an object to signal the occurrence of an action. The action could be caused by user interaction, such as a button click, or it could be raised by some other program logic, such as changing a property’s value. The object that raises the event is called the event sender.” (Handling and Raising Events - .NET | Microsoft Learn)For instance, suppose you have a Keyboard.cs script that waits for certain keyboard keys to be hit in order for the Keyboard to do its thing such as LEFT arrow. For this, our Keyboard when it sees the LEFT arrow getting hit it needs to report this to the InputManager and say “Hey trigger movement LEFT”, the InputManager does not care if this came from a touch controller or Keyboard it just waits until something happens and it then fires off its events. So we now have to add our event add this public event Action move; under the delegate. This is now how we can connect our controllers to InputManager so it can react to interactions from the user such Keystrokes, touches or whatever you want even accelerometer for devices that support this. Does this makes sense or am I losing you? I want to make sure you start off with good code designs and good coding styles so you can be a great coder.
Haha okay, ima step out really quick be back in 15 min. Read over the notes and look at the MSDN definitions so you can get a good perspective. Once you see your player moving around you will see how good code design can make things a lot easier for you
Actually, I had an idea of what you were saying, but now I’m confused at what to do. I made the InputManager script but what do I do with it? How do I tell it which key does what, and how do I ge those keys to actually do something?
I’m back. As to your first question, we are going to create our KeyboardController.cs script and from there you will see how EVERYTHING comes together.
As to your second question it really depends on the original textures. If the original textures are low res and you try to scale them up it can cause a loss in resolution as the pixels become stretched.
So looking back so we can finish off our InputManager we need to create the method that will be triggered by any of our controllers when an event is raised.
Add this method to InputManager
// Event Invocation
public void Move(MovementType direction, Vector3 movementVector = default(Vector3)) {
// Checks if the event trigger has any methods registered to it.
if(this.move != null) {
// If it does execute those methods.
this.move(direction, movementVector);
}
}
Understand this, I named the method “Move” BUT it does not need to be called this. You can call it whatever you want to call it totally up to you. The method signature for the parameter list MUST be the same as the delegate.
So now in Unity3D:
1.) Create an empty Game Object
2.) Add the InputManager script to it.
3.) Create a tag “InputManager”
4.) Assign the tag to the new Game Object
5.) Rename the Game Object to “InputManager” (Optional, but lets you know what this game object is doing.)