Im making a jump script for my game, but it won't jump - c#

The way my code works is it checks if touching the ground, then if its true, it waits for space to get put in as an input, then if both statements are true, it uses the rigid body method to propel itself into the air.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Jump : MonoBehaviour
{
public string objectName;
public Rigidbody rb;
public int h;
// Start is called before the first frame update
void OnCollisionEnter(Collision col)
{
if(col.gameObject.name == objectName){
Debug.Log("On ground statement is true.");
if(Input.GetKey("space"))
{
rb.AddForce(0, h, 0);
}
}
}
}
The problem is, when i run it, it knows its on ground, but it won't respond to key inputs.
I know it can't be a problem with my computer, as my other controls work.

It's a bad idea to be testing for player input inside a collision event - if the player is pressing space, it will only ever register during the exact same frame that the object collided with something. A better place for that would be the Update() method, which happens every frame.
You should also create a variable that stores whether the player is currently on the ground or not, based on your collision events. Your input code will check this variable when deciding if the player is allowed to jump.
Try this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Jump : MonoBehaviour
{
public string objectName;
public Rigidbody rb;
public int h;
public bool onGround = false; // new
// get your player input in here instead
void Update()
{
if(onGround && Input.GetKey("space"))
{
rb.AddForce(0, h, 0);
}
}
void OnCollisionEnter(Collision col)
{
if(col.gameObject.name == objectName){
Debug.Log("On ground statement is true.");
onGround = true; // new
}
}
// new
void OnCollisionExit(Collision col)
{
if(col.gameObject.name == objectName){
Debug.Log("No longer on the ground.");
onGround = false;
}
}
}

Related

collision between player and a limiter is not 100% functional

In the game I'm developing, the player moves left and right avoiding obstacles that fall from above, but when the player reaches the left or right limit, a collision bug may occur and he simply leaves the screen. I'm using the rigidbody.velocity and the trigger to check for collision but even so, there are times when it manages to cross the wall. Here the script.(And I'm not using FixedUpdate because it's not responding well when I tap the screen.)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Ball : MonoBehaviour
{
public bool isRight;
public float speed;
public Transform pointR;
public Transform pointL;
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if(isRight)
{
rb.velocity = new Vector2(speed, 0);
}
else
{
rb.velocity = new Vector2(-speed, 0);
}
if(Input.GetMouseButtonDown(0))
{
isRight = !isRight;
}
}
void OnTriggerEnter2D(Collider2D collider)
{
if(collider.CompareTag("ColisorEs"))
{
isRight = !isRight;
}
if(collider.CompareTag("colisorR"))
{
isRight = !isRight;
}
}
}
Rigidbody changes should be handled in the FixedUpdate methode. It's better for Unitys Physics.
You can leave your Input.GetMouseButtonDown in Update.

Unity OnControllerColliderHit detecting not detecting correctly

I am trying to teleport the character when they touch a cube, but for some reason, it prints the message that it the collision is being detected, but the character's position is not changing. It works for another scenario that is almost exactly the same, but even if I put this in another script, it does not teleport the character. Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class othercollision : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void OnControllerColliderHit(ControllerColliderHit hit)
{
if (hit.gameObject.name == "teleportcube")
{
gameObject.transform.position = new Vector3(-3184.53f, 20.35f, -171.585f);
Debug.Log("Collision detected");
}
}
}
Here is the script that has something similar working:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
public class detectcollision : MonoBehaviour
{
public GameObject tplocation1;
public GameObject player;
public GameObject entranceloc;
void OnControllerColliderHit(ControllerColliderHit hit)
{
//This if statement does Debug.Log the message and it also changes the player's position.
if (hit.gameObject.name == "trigger")
{
Debug.Log("triggered");
gameObject.transform.position = tplocation1.transform.position;
Thread.Sleep(7);
Application.Quit();
}
//This if statement does not change the player's position, but Debug.Logs the teleporting message.
if (hit.gameObject.name == "entrance")
{
gameObject.transform.position = new Vector3(-3184.53f, 20.35f, -171.585f);
Debug.Log("teleporting...");
}
}
}
Try to make the Vector3 beforehand as a variable or a temporary variable and then assign it to the position. If you did then maybe the values that you have entered are out of boundary somewhy, but that's unlikely, try changing them.

Retrive objects from a list and teleport them to a specific location in Unity

and thank you for looking at this in advance.
I have yet another problem that i need to solve and it goes like this:
I have a list of objects that i select with a raycast, and i would like to teleport them to a specific location in the scene. Like for example i have selected a cube and a sphere and they are added to my list called playersTagged.
How can i get the objects in my list to that specific location when OnCollisionEnter with my player that has the tag "Tagger"?
My code looks like this:
PlayerTagged Class
using System.Collections.Generic;
using UnityEngine;
public class PlayerTagged : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public Camera fpsCam;
public List<GameObject> playersTagged;
private void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
}
void Shoot()
{
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Target target = hit.transform.GetComponent<Target>();
if (target != null && target.isHit == false)
{
target.takeDamage(damage);
if(hit.collider.tag == "Taggable")
playersTagged.Add(hit.collider.gameObject);
target.isHit = true;
}
}
}
}
Teleport class:
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Transform teleportTarget;
public PlayerTagged player;
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Tagger")
{
Debug.Log("You hit the can");
}
}
}
You need to have the PlayerTagged reference in your Teleport component. If both objects will always exist in your scene, only create a public field in your Teleport and drag and drop your PlayerTagged ref, otherwise you will need to fill this ref by code using some "find" approach, for example, GameObject.FindObjectWithTag().
You can also make an event that trigger when the object that entered the OnTriggerEnter is valid (I mean, when your tag condition pass) and then make sure that PlayerTagged is being registered as listener to this event.
First one is easier to setup, but if you plan to make unique things with this OnTriggerEnter as playing sounds, changing data or something like that, the second one is a better approach.
EDIT: I'll try to insert some code, let me know if you still having problems on getting the idea
"If both objects will always exist in your scene..."
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Transform teleportTarget;
public PlayerTagged player; // I didn't saw that you already have an ref here, my bad, so you only need to access the fields
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Tagger")
{
Debug.Log("You hit the can");
var list = player.playersTagged; // this is how you will access your list
// Do some stuff with your list
}
}
}
Ignore the rest, it will only complicate things
EDIT 2: Making the teleport happen in player, and teleport every object
using System.Collections.Generic;
using UnityEngine;
public class PlayerTagged : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public Camera fpsCam;
public List<GameObject> playersTagged;
private void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
}
// Option 1:
private void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "Teleport Tag")
{
var teleport = col.gameObject.GetComponent<Teleport>();
TeleportObjectsTo(teleport.teleportTarget.position);
}
}
void Shoot()
{
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Target target = hit.transform.GetComponent<Target>();
if (target != null && target.isHit == false)
{
target.takeDamage(damage);
if(hit.collider.tag == "Taggable")
playersTagged.Add(hit.collider.gameObject);
target.isHit = true;
}
}
}
public void TeleportObjectsTo(Vector3 targetPosition)
{
foreach(taggedObjects in playersTagged)
{
taggedObjects.transform.position = targetPosition;
}
}
}
You can also make the teleport happen on teleport script:
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Transform teleportTarget;
public PlayerTagged player; // I didn't saw that you already have an ref here, my bad, so you only need to access the fields
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Tagger")
{
Debug.Log("You hit the can");
// Option 2:
player.TeleportObjectsTo(teleportTarget);
// Option 3: Or you can iterate here instead of make use of the API
foreach(var taggedObjects in player.playersTagged)
{
taggedObjects.transform.position = targetPosition;
}
}
}
}
Chose one option, and delete/comment others
--N

reference from various scripts causing problems [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 1 year ago.
For some reason when I'm in the normal view in-game I am able to link the scripts that I need to call in order to make an animation like so
however, whenever I start the game it automatically removes them from the slots, and it doesn't work
I am completely clueless as to why this may be happening and unity keep giving me errors that say that I'm not setting an instance to my script I really have no clue why this may be happening.
I have 3 scripts that I'm working with that is giving me the problem
one is the main script for the enemy vision (I am referencing the other scripts in this one)
the second is the enemy animation script which makes him go from idle to attack and the third is an animation for the gun model since I had to make it follow the hands of the enemy
scripts attached bellow
1st script(enemyAI):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyAi : MonoBehaviour
{
public bool detected;
GameObject target;
public Transform enemy;
public GameObject Bullet;
public Transform shootPoint;
public float shootSpeed = 10f;
public float timeToShoot = 1f;
public EnemyAni Animation;
public GunAni GunAnimation;
void Start()
{
Animation = GetComponent<EnemyAni>();
GunAnimation = GetComponent<GunAni>();
}
public void Update()
{
//makes the enemy rotate on one axis
Vector3 lookDir = target.transform.position - transform.position;
lookDir.y = 0f;
//makes enemy look at the players position
if (detected)
{
enemy.LookAt(target.transform.position, Vector3.up);
enemy.rotation = Quaternion.LookRotation(lookDir, Vector3.up);
}
if (detected == true)
{
Animation.LookPlayer = true;
GunAnimation.ShootPlayer = true;
}
if (detected == false)
{
Animation.LookPlayer = false;
GunAnimation.ShootPlayer = false;
}
}
//detects the player
void OnTriggerEnter(Collider other)
{
if (other.tag == "Player")
{
detected = true;
target = other.gameObject;
}
}
void OnTriggerExit(Collider other)
{
if (other.tag == "Player")
{
detected = false;
}
}
}
2nd Script (EnemyAnimation):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyAni : MonoBehaviour
{
public Animator animator;
public bool LookPlayer;
public void Start()
{
animator = GetComponent<Animator>();
}
public void Update()
{
if (LookPlayer == true)
{
animator.SetBool("IsShootingStill", true);
}
else
{
animator.SetBool("IsShootingStill", false);
}
}
}
3rd script (GunAnimation):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunAni : MonoBehaviour
{
public Animator animator;
public bool ShootPlayer;
public void Start()
{
animator = GetComponent<Animator>();
}
public void Update()
{
if (ShootPlayer == true)
{
animator.SetBool("IsShooting", true);
}
else
{
animator.SetBool("IsShooting", false);
}
}
}
Your code:
void Start()
{
Animation = GetComponent<EnemyAni>();
GunAnimation = GetComponent<GunAni>();
}
Searches the GameObject that holds the EnemyAI script for EnemyAni and GunAni. If the GameObject doesn't have those it will return null.
Sounds like you want to remove that code.
Note that if the scripts exist on a child of that GameObject you will need to use GetComponentInChildren
There are some things to review, good practices:
GameObject target is private for C#, but it is better to put private before.
variable names like Bullet Animation GunAnimation should always begin with lowercase, because they might be confused with a Class Name (search in internet for CamelCase and PascalCase).
Name should be clear. EnemyAni Animation is not clear enough, because Animation maybe any animation (player, enemy, cube, car, etc.).
It is better enemyAnimation to be clear, as you did with GunAnimation (only just with lower case at beginning)
As slaw said, the Animation must be in the GO attached.
about last item
Let's say you have an empty GO (GameObject) called GameObject1 and you attach EnemyAi script to it.
In Runtime (when game mode begins), it will try to find Animation = GetComponent<EnemyAni>();, but it won't find it
Why?
Because GetComponent<> searches for the Component(Class) that is in the <> (in this case EnemyAni) in its GO (in this case, GameObject1), but the unique script attached to GameObject1 is EnemyAI.
So, you have 3 options:
Attach EnemyAni to GameObject1
Create another GO (for example, GameObjectEnemyAni), attach the script EnemyAni and drag and drop GameObjectEnemyAni to GameObject1 and delete Animation = GetComponent<EnemyAni>(); in Start
Keep in mind: if you leave that line of code, instead of getting the script EnemyAni from GameObjectEnemyAni, it will run the code Animation = GetComponent<EnemyAni>(); in Start, and obviously, it won't find it
Create events. It's a really good practice for avoiding code tight coupling, but that is more advanced stuff.

Unity problem activating a function with parameters in camera from another script in GameObject Enemy

I have a script that makes the camera do a shake by putting a button because
It is a public access function, if I do it that way when placing a button it works well but what I cannot achieve is to call the function so that every time my player collides with an enemy he makes the shake. I hope you can help me.
The shake code in camera is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScreenShaker : MonoBehaviour {
private float shakeAmount = 0.5f;
private float shakeTime = 0.0f;
private Vector3 initialPosition;
private bool isScreenShaking = false;
void Update () {
if(shakeTime > 0)
{
this.transform.position = Random.insideUnitSphere * shakeAmount + initialPosition;
shakeTime -= Time.deltaTime;
}
else if(isScreenShaking)
{
isScreenShaking = false;
shakeTime = 0.0f;
this.transform.position = initialPosition;
}
}
public void ScreenShakeForTime(float time)
{
initialPosition = this.transform.position;
shakeTime = time;
isScreenShaking = true;
}
}
The enemy code is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ControladorEnemigoCirculoMediano : MonoBehaviour
{
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
Here I don't know what to call the public void function ScreenShakeForTime (float time);
I already tried many things online but when my character comes into contact with the character, I don't do the shake in the camera.
}
}
}
You can create Unity-singleton in your ScreenShaker class like:
class ScreenShaker
{
public static ScreenShaker Instance {private set; get;};
void Awake() {
Instance = this;
}
}
And than from any place to call like:
ScreenShaker.Instance.ScreenShakeForTime(2f);
This is the easiest way, but maybe it's better to create standard singeleton(it's up to you).
And also don;t forget to destroy it on OnDestroy()
can you tell me in enemy game object collider isTrigger is enable or not
if it is not enable then use OnColliderEnter2D(Collision2D other){} for collision detection

Categories

Resources