I have a player and a platform on my scene. The scene is in 2D.
Here are platform's components:
Here are player's components:
[]
To move the player - I use SimpleMove() method:
CharacterController controller;
public float speed = 3.0F;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update()
{
float movement = Input.GetAxis("Horizontal");
Vector2 movementVector = new Vector2(movement, 0f);
controller.SimpleMove(movementVector * speed);
}
I'm afraid what you're trying to achieve will not work as expected. Character Controller is actually intended for 3D and you're expecting it to collide with 2D colliders that works differently and most importantly are not compatible
Character Controller brings 3D capsule collider to it's object - see https://docs.unity3d.com/Manual/class-CharacterController.html
You may try to experiment with adding some 2D collider and eventually also RigiBody2D to your object. Character Controller is intended also for cases without using physics (except collisions), so if that's the case also for your 2D game, creating own character controller could be quite straight forward option as well
Related
I'm currently trying to create a multiplayer game using mirror!
So far I've been successful in creating a lobby and set up a simple character model with a player locomotion script I've taken and learnt inside out from Sebastian Graves on YouTube (you may know him as the dark souls III tutorial guy)
This player locomotion script uses unity's package 'Input System' and is also dependent on using the camera's .forward and .right directions to determine where the player moves and rotates instead of using forces on the rigidbody. This means you actually need the camera free in the scene and unparented from the player.
Here is my HandleRotation() function for rotating my character (not the camera's rotation function):
private void HandleRotation()
{
// target direction is the way we want our player to rotate and move // setting it to 0
Vector3 targetDirection = Vector3.zero;
targetDirection = cameraManager.cameraTransform.forward * inputHandler.verticalInput;
targetDirection += cameraManager.cameraTransform.right * inputHandler.horizontalInput;
targetDirection.Normalize();
targetDirection.y = 0;
if (targetDirection == Vector3.zero)
{
// keep our rotation facing the way we stopped
targetDirection = transform.forward;
}
// Quaternion's are used to calculate rotations
// Look towards our target direction
Quaternion targetRotation = Quaternion.LookRotation(targetDirection);
// Slerp = rotation between current rotation and target rotation by the speed you want to rotate * constant time regardless of framerates
Quaternion playerRotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
transform.rotation = playerRotation;
}
It's also worth mentioning I'm not using cinemachine however I'm open to learning cinemachine as it may be beneficial in the future.
However, from what I've learnt and managed to find about mirror is that you have to parent the Main Camera under your player object's prefab so that when multiple people load in, multiple camera's are created. This has to happen on a Start() function or similar like OnStartLocalPlayer().
public override void OnStartLocalPlayer()
{
if (mainCam != null)
{
// configure and make camera a child of player
mainCam.orthographic = false;
mainCam.transform.SetParent(cameraPivotTransform);
mainCam.transform.localPosition = new Vector3(0f, 0f, -3f);
mainCam.transform.localEulerAngles = new Vector3(0f, 0f, 0f);
cameraTransform = GetComponentInChildren<Camera>().transform;
defaultPosition = cameraTransform.localPosition.z;
}
}
But of course, that means that the camera is no longer independent to the player and so what ends up happening is the camera rotates when the player rotates.
E.g. if I'm in game and looking to the right of my player model and then press 'w' to walk in the direction the camera is facing, my camera will spin with the player keeping the same rotation while my player spins in order to try and walk in the direction the camera is facing.
What my question here would be: Is there a way to create a system using mirror that doesn't require the camera to be parented to the player object prefab on start, and INSTEAD works by keeping it independent in the scene?
(I understand that using forces on a rigidbody is another method of creating a player locomotion script however I would like to avoid that if possible)
If anybody can help that would be greatly appreciated, Thank You! =]
With the constraint of your camera being attached to the player you will have to adapt the camera logic. What you can do is instantiate a proxy transform for the camera and copy that transforms properties to your camera, globally, every frame. The parent constraint component might do this for you. Then do all your transformations on that proxy.
Camera script with instantiation:
Transform proxy;
void Start(){
proxy = (new GameObject()).transform;
}
void Update(){
//transformations on proxy
transform.position = proxy.position;
transform.rotation = proxy.rotation;
}
I am trying to create a carrom 2D game for learning, i added box colliders 2D all sides and for striker circle collider 2D, and set physics material for all as friction 0 and bounciness 1. and Linear Drag to 1 for stiker.
It all works fine when velocity of impact of striker with sides but velocity is slow its dragging on slides instead of bouncing. where am i doing it wrong?
I am not sure what the problem is but seems like something to do with how the engine is resolving the physics. Try resolving the collision for the individual carrom tokens manually when they hit a surface instead of relying on physics material.
Here is a simple 2D example:
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
public class ReflectingObject : MonoBehaviour {
[Range(0f, 1f)]
public float bounciness = 1;
private Rigidbody2D m_Rb;
void Awake() {
m_Rb = GetComponent<Rigidbody2D>();
}
void OnCollisionEnter2D(Collision2D col) {
if(col.contactCount > 0) {
// Get the collision contact point
ContactPoint2D point = col.contacts[0];
// Get the current speed of this object
float speed = m_Rb.velocity.magnitude;
// Get the direction where this object is heading to
Vector2 oldDirection = (Vector2)m_Rb.velocity.normalized;
// Get the reflected direction
Vector2 newDirection = Vector2.Reflect(oldDirection, point.normal).normalized;
// Calculate new velocity based on bounciness
Vector2 newVelocity = newDirection * speed * bounciness;
// Assign the velocity
m_Rb.velocity = newVelocity;
}
}
}
Something like this.
Assign this Component to the objects which you want to reflect on collision.
My 3d ball was moving continuously in the forward direction so I want to give X-rotation for this plus game player was dragging ball horizontally on the screen so for this horizontal movement, I want to give Z-rotation.
To achieve my desire, the result I have made ball parent and child game objects, where parent game object only contains collider and rigidbody and this will do the actual physical movement.
Another side, child game object only contains mesh renderer, this will do desire rotation.
Following image gives you more idea about my structure:
Ball Parent:
Ball Child:
For giving rotation to ball mesh as like parent physics ball, I have written this code:
public class BallMeshRolling : MonoBehaviour
{
private Vector3 ballLastPosition;
void Start ()
{
ballLastPosition = transform.parent.position;
}
void Update ()
{
//implementation-1
//float speed = Vector3.Distance (transform.parent.position, ballLastPosition) * 30f;
//transform.RotateAround (transform.position, Vector3.right, speed);
//implementation-2
//Vector3 differenceInPosition = (transform.parent.position - ballLastPosition).normalized;
//transform.Rotate (differenceInPosition * 10f);
//implementation-3
Vector3 differenceInPosition = (transform.parent.position - ballLastPosition).normalized * 50f;
Quaternion rotation = Quaternion.LookRotation(differenceInPosition);
transform.rotation = rotation;
ballLastPosition = transform.parent.position;
}
}
But none of the above ways working properly, so I expect some other better suggestions from your side.
EDIT: Overall I am trying to achieve something like this:
Catch up - Ketchapp - Highscore 1274
There is a tutorial series from Unity about rolling and moving a 3d ball that can help you to figure out the basics for your problem. Wish it could help.
Roll-a-ball tutorial in Unity Tutorials
I'm trying to learn Unity by myself. I'm recreating pong in 3d with Unity objects. I started a few minutes ago and every time I throw any input into the pad its y coordinate shifts to 2.6, I have no idea why. Can someone help?
public class PadMovement : MonoBehaviour {
private CharacterController pad;
private Vector3 direction;
private Vector3 movement;
[SerializeField] private float speed = 50.0f;
// Use this for initialization
void Start() {
pad = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update() {
direction = new Vector3(Input.GetAxis("Horizontal"), 0, 0);
movement = direction * speed;
pad.Move(movement * Time.deltaTime);
}
}
SOLVED: there was a capsule collider out of place!
Afternoon, I recently copied your code into a 'Unity3d', ".cs", File and actually I created a cube and placed my game into a 2d mode, After this I named my file "PadMovement", after that I dragged it onto my newly created cube, Once I had done that I tried to click play and noticed that my cube didn't have a "CharacterController", attached to my cube, Once I had done that and clicked play I was eligible to have my "paddle", smoothly move around the screen # 50.0f along the X axis.
Knowingly, My Input came from the "Character Controller", My Speed came from the Serial field you had for speed!
Do you by any chance have a CapsuleCollider Component or some other collider on the same GameObject that you have this PadMovement Component on? That sounds like a height where it might just be trying to pop the object out of ground collision.
It should be harmless if that's all it is. If you really want an object to be at y of 0 you can attach it to a parent object and have that parent stay at 0.
I am very new to Unity and just got done yesterday following the Roller Ball example on the learn page here at Unity3d.
To practice what I have learned I wanted to try and recreate something similar using my own art and making the game different. I have been playing around with Voxel Art and I am using MagicaVoxel to create my assests. I created the walls, the ground etc.. and all is well.
Then came the player object, the sphere. I created one as close to a sphere as possible with magicaVoxel and it rolls fine. However, when using a script to have the camera follow the object it runs into issues.
If I don't constrain the Y axis then I will get bouncing and as far as the x and z axis I get kind of a Flat Tire effect. Basically the camera doesn't follow smoothly it bounces around, stop go etc...
I have tried making the collider larger then the sphere and even using the position of the collider vs the object itself. I have also tried putting the code in Update / FixedUpdate / LateUpdate. What is the proper way to fix or address something like this? Here is my scripts below:
Camera Controller:
public class CamController : MonoBehaviour {
public GameObject player;
private Vector3 offset;
void Start ()
{
// Get the distance between the player ball and camera.
offset = this.transform.position - player.transform.position;
}
void LateUpdate ()
{
this.transform.position = player.transform.position + offset;
}
}
Player Controller:
public class PlayerController : MonoBehaviour {
public float _speed;
void FixedUpdate()
{
// Get input from keyboard.
float _hoz = Input.GetAxis("Horizontal");
float _ver = Input.GetAxis("Vertical");
// Create a vector3 based on input from keyboard.
Vector3 _move = new Vector3(_hoz, 0.0f, _ver);
// Apply force to the voxel ball
this.GetComponent<Rigidbody>().AddForce(_move * _speed);
}
}
Thanks for any help in advance.
You can use the SmoothFollow Script of Unity it self for getting smooth follow of camera.
Here are the steps how you can get the script:
1) Assets->Import Package->Scripts.
2) At the dialog that appears select all the scripts, or just the smooth follow one and hit Import button.
3) Now this script is in your project, and you can attach it to the camera.
Hope this will help you...
Best,
Hardik.