Jumping with CharacterController doesnt work? - visual-studio

I am very new to coding and i am trying to make a FPS, but i can't get the jumping mechanic to work. I am following a tutorial of Brackeys : https://www.youtube.com/watch?v=_QajrabyTJc
I have tried changing the standard jumping bind, i have tried using GetKeyDown(KeyCode.Space) instead of using GetButtonDown("Jump") , but nothing seems to work. Anybody knows how to fix this? I love you. Have been struggling for 16 hours now...
using System.Collections.Generic;
using UnityEngine;
public class playermm : MonoBehaviour
{
public CharacterController controller;
public float speed = 12f;
public float gravity = -9.81f;
public float jumpHeight = 3f;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
Vector3 velocity;
bool isGrounded;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if(isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
if(Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}

Here is what I recommend.
Type in this command at the end:
Debug.Log(isGrounded);
It should print true if the character is on the ground. If it prints true, then the error is with your velocity and moving the character or square root expression.
If it prints false, then the problem is with your ground check. you should check the position of 'groundCheck', if it is at the bottom of the charcter, then that is okay. Next, check the 'groundDistance', if the value is about 0.5, it should be okay. Then check the groundMask. If the groundMask is the same mask that the ground is applied to, then that is fine. If it returned true, then one of these is wrong.
Links for extra help:
https://docs.unity3d.com/ScriptReference/LayerMask.html
https://docs.unity3d.com/ScriptReference/Physics.CheckSphere.html
Write back to me.

Related

Unity determining ground via raycasting 2d

Good evening!
I am trying to make a simple 2d platformer in unity without using rigidbodies, so I use raycast to determine where is the ground. I wrote this code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class comtroller : MonoBehaviour
{
private float velocity_y;
private float velocity_x;
private float speed_y = 1;
private float speed_x = 10;
private float localMinimum_y;
//mask of the platform
public LayerMask mask;
void Update()
{
// raycast to sense platforms
RaycastHit2D hit = Physics2D.Raycast((Vector2)transform.position , Vector2.down,Mathf.Infinity, mask);
if (hit)
{
localMinimum_y = hit.point.y;
}
else
{
localMinimum_y = -10;
}
//determine whether the player can fall down
// -0.6 is the distance between the player's transform.position and his legs
if(transform.position.y -0.6f < localMinimum_y)
{
speed_y = 0;
}
else
{
speed_y = 1;
}
//determine velocities
velocity_y = speed_y * Physics2D.gravity.y * Time.deltaTime;
velocity_x = Input.GetAxis("Horizontal") * speed_x * Time.deltaTime;
//movement
transform.Translate(new Vector2(velocity_x, velocity_y));
}
}
However, the player keeps stucking in the platform.
Can anyone help me where is the problem and how can I cure it?
Or if my idea is completely bad can you give any suggestion about how to do it?
Thank you
I recommend following this tutorial if you want to go the non rigidbody way of making a 2d platformer game. It shows you how to manage raycast to make a character move on ground, slope, platforms and many other things. It's really ressourceful and will probably help you a lot.

How to rotate a rigidBody2d in a fixed period?

I'm new in Unity development. I have a ball with RigidBody 2D on it and i want it to rotate for 1 second. Does not matter the speed. The speed can be automatically.
I want just : at second 0 to be in initial position and at second 1 to be in final position. The rotation can be : 180, 360, 720.. etc degree.
I tried with angularVelocity but never stops. I tried with add torque but same. I don't know to handle it.
rb.angularVelocity = 180;
or
rb.AddTorque(90);
If you want to reach a precise rotation after a certain amount of time, it means your rotation speed will be computed automatically. To achieve something like this I'd recommend using a Coroutine :
public class TestScript : MonoBehaviour
{
public float targetAngle;
public float rotationDuration;
void Update()
{
//This is only to test the coroutine
if(Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine(RotateBall(targetAngle, rotationDuration));
}
}
private IEnumerator RotateBall(float a_TargetAngle, float a_Duration)
{
Vector3 startLocalEulerAngles = GetComponent<RectTransform>().localEulerAngles;
Vector3 deltaLocalEulerAngles = new Vector3(0.0f, 0.0f, a_TargetAngle - startLocalEulerAngles.z);
float timer = 0.0f;
while(timer < a_Duration)
{
timer += Time.deltaTime;
GetComponent<RectTransform>().localEulerAngles = startLocalEulerAngles + deltaLocalEulerAngles * (timer / a_Duration);
yield return new WaitForEndOfFrame();
}
GetComponent<RectTransform>().localEulerAngles = startLocalEulerAngles + deltaLocalEulerAngles;
}
}

When dragging an object with rigidbody2D it passes through colliders (walls)

Ok, so I'm making this game where the user can drag a ball around the screen, but it's not supposed to leave the play area. I'm getting the following problem though, when I push it towards the colliders it bounces back, and if I push too hard it simply goes off screen (I need to make it do not go off screen. the user is free to drag it all over the place, but within the screen of course).
any tips on how I could solve this issue?
Here is the code for dragging which I'm using:
using UnityEngine;
using System.Collections;
public class CircleManager : MonoBehaviour {
private bool dragging = false;
private Vector3 screenPoint;
private Vector3 offset;
// Pressionando
void OnMouseDown()
{
dragging = true;
screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position);
offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
}
// Arrastando
void OnMouseDrag()
{
Vector3 cursorPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
Vector3 cursorPosition = Camera.main.ScreenToWorldPoint(cursorPoint) + offset;
//i tried with both below.
//transform.position = cursorPosition;
transform.GetComponent<Rigidbody2D>().MovePosition(cursorPosition);
}
// Soltando
void OnMouseUp()
{
dragging = false;
}
}
Thanks!
You could try to do something like,
if( transform.position.x > xMaxPos )
{
transform.position.x = new Vector3( xMaxPos, transform.position.y, transform.position.z );
}
You could set up for each min and max. Then when you create the xMaxPos variables, create them like:
[serializeField]
private float xMaxPos;
That way they will appear in the inspector and you can tweak their values as you please. You could also throw in an offset that's the width of the ball i.e.
transform.position.x = new Vector3( xMaxPos - transform.localscale.x/2, transform.position.y, transform.position.z );
Try using velocity
public class CircleManager : MonoBehaviour {
private bool dragging = false;
private Vector3 screenPoint;
private Vector3 offset;
public float speed = 5.0f;
// Pressionando
void OnMouseDown()
{
dragging = true;
Vector3 cursorPosition = Camera.main.ScreenToWorldPoint(ToDepth(Input.mousePosition, transform.position.z));
offset = gameObject.transform.position - cursorPosition;
}
// Arrastando
void OnMouseDrag()
{
Vector3 cursorPosition = Camera.main.ScreenToWorldPoint(ToDepth(Input.mousePosition, transform.position.z)) + offset;
Vector3 direction = (transform.position - cursorPosition).normalized;
transform.GetComponent<Rigidbody2D>().velocity = direction * speed * Time.deltaTime;
}
// Soltando
void OnMouseUp()
{
dragging = false;
}
Vector3 ToDepth(Vector3 value, float depth)
{
return new Vector3(value.x, value.y, depth);
}
}
Few things to note:
You don't have to write out gameObject.transform.position i see you did that a few times, as well as calling transform... directly. Its both the same thing, so you don't need the gameObject part.
Also your getting the screenPoint of the transform, then using the z value of that later on, which doesn't really make much sense to me.
Anyways, i don't see why this shouldn't work for you, i haven't tested it though.

Animate/move/translate/tween image in Unity 4.6 from C# code

How can I move/animate/translate/tween an Image from position A to position B using C# code in Unity 4.6?
Assuming Image is a GameObject, so it could be a Button or whatever.
There has to be a one-liner for this, right? I've been googling for a while but all I can see out-of-the-box is stuff done in Update, and I firmly believe doing stuff in Update is not a fast way of scripting things.
maZZZu's method will work, however, if you do NOT want to use the Update function, you can use an IEnumerator/Coroutine like so…
//Target object that we want to move to
public Transform target;
//Time you want it to take before it reaches the object
public float moveDuration = 1.0f;
void Start ()
{
//Start a coroutine (needed to call a method that returns an IEnumerator
StartCoroutine (Tween (target.position));
}
//IEnumerator return method that takes in the targets position
IEnumerator Tween (Vector3 targetPosition)
{
//Obtain the previous position (original position) of the gameobject this script is attached to
Vector3 previousPosition = gameObject.transform.position;
//Create a time variable
float time = 0.0f;
do
{
//Add the deltaTime to the time variable
time += Time.deltaTime;
//Lerp the gameobject's position that this script is attached to. Lerp takes in the original position, target position and the time to execute it in
gameObject.transform.position = Vector3.Lerp (previousPosition, targetPosition, time / moveDuration);
yield return 0;
//Do the Lerp function while to time is less than the move duration.
} while (time < moveDuration);
}
This script will need to be attached to the GameObject that you would like to move. You will then need to create another GameObject in the scene that will be your Target…
The code is commented but if you need clarification on something just post a comment here.
If you want to do the movement yourself you can use something like this:
public Vector3 targetPosition = new Vector3(100, 0, 0);
public float speed = 10.0f;
public float threshold = 0.5f;
void Update () {
Vector3 direction = targetPosition - transform.position;
if(direction.magnitude > threshold){
direction.Normalize();
transform.position = transform.position + direction * speed * Time.deltaTime;
}else{
// Without this game object jumps around target and never settles
transform.position = targetPosition;
}
}
Or you can download for example DOTween package and just start the tween:
public Vector3 targetPosition = new Vector3(100, 0, 0);
public float tweenTime = 10.0f;
void Start () {
DOTween.Init(false, false, LogBehaviour.Default);
transform.DOMove(targetPosition, tweenTime);
}

Rotation in Unity3D

This is a simplified code from what I'm trying to do:
var angle = 1.57;
if ( this.transform.rotation.y > angle ){
this.transform.rotation.y--;
} else if ( this.transform.rotation.y < angle ){
this.transform.rotation.y++;
}
I'm used to code in AS3, and if I do that in flash, it works perfectly, though in Unity3D it doesn't, and I'm having a hard time figuring out why, or how could I get that effect.
Can anybody help me? Thanks!
edit:
my object is a rigidbody car with 2 capsule colliders driving in a "bumpy" floor, and at some point he just loses direction precision, and I think its because of it's heirarchical rotation system.
(thanks to kay for the transform.eulerAngles tip)
transform.rotation retrieves a Quaternion. Try transform.rotation.eulerAngles.y instead.
Transform Rotation is used for setting an angle, not turning an object, so you would need to get the rotation, add your change, and then set the new rotation.
Try using transform.rotate instead.
Check the Unity3d scripting reference here:
http://unity3d.com/support/documentation/ScriptReference/Transform.Rotate.html
I see two problems so far. First the hierarchical rotation of Unity. Based on what you are trying to achieve you should manipulate either
transform.localEulerAngles
or
transform.eulerAngles
The second thing is, you can't modify the euler angles this way, as the Vectors are all passed by value:
transform.localEulerAngles.y--;
You have to do it this way:
Vector3 rotation = transform.localEulerAngles;
rotation.y--;
transform.localEulerAngles = rotation;
You need to create a new Quaternion Object
transform.rotation = Quaternion.Euler ( transform.rotation.x, transform.rotation.y++, transform.rotation.z );
You can also use transform.Rotate function.
The above suggestion to use transform.Rotate( ) is probably what you're going to need to do to actually make it rotate, BUT the variables of transform.Rotate( ) are velocity/speed rather than direction, so transform.Rotate( ) will have to use more than one axis if you want an angled rotation. Ex:
class Unity // Example is in C#
{
void Update( )
{
gameObject.transform.Rotate(0, 1, 0);
}
}
This will rotate the object around its y-axis at a speed of 1.
Let me know if this helps - and if it hinders I can explain it differently.
You should try multiplyng your rotation factor with Time.deltaTime
Hope that helps
Peace
Here is my script for GameObject rotation with touch
//
// RotateController.cs
//
// Created by Ramdhan Choudhary on 12/05/13.
//
using UnityEngine;
using System;
public class RotateController
{
private float RotationSpeed = 9.5f;
private const float mFingerDistanceEpsilon = 1.0f;
public float MinDist = 2.0f;
public float MaxDist = 50.0f;
private Transform mMoveObject = null;
private bool isEnabledMoving = false;
//************** Rotation Controller Constructor **************//
public RotateController (Transform goMove)
{
isEnabledMoving = true;
mMoveObject = goMove;
if (mMoveObject == null) {
Debug.LogWarning ("Error! Cannot find object!");
return;
}
}
//************** Handle Object Rotation **************//
public void Update ()
{
if (!isEnabledMoving && mMoveObject != null) {
return;
}
Vector3 camDir = Camera.main.transform.forward;
Vector3 camLeft = Vector3.Cross (camDir, Vector3.down);
// rotate
if (Input.touchCount == 1) {
mMoveObject.Rotate (camLeft, Input.touches [0].deltaPosition.y * RotationSpeed * Time.deltaTime, Space.World);
mMoveObject.Rotate (Vector3.down, Input.touches [0].deltaPosition.x * RotationSpeed * Time.deltaTime, Space.Self);
}
}
}

Resources