I'm having trouble finding my mistake regarding my automatic movement script. I will explain first what i tried to do so you can understand it better. So i am programming in c# in unity. It is for VR. I created a button, that works as a trigger when you are looking at it. When looking at the button a door goes down and the player should move inside a castle (automatically).
The door script works fine but the player is not moving at all. I used a public Vector3 where I declared the position inside the castle where the player should move to (it is only a forward direction).
Unfortunately the code looks fine to me and i cant figure it out why my player wont move :/.
So I tried playing around with the Vectors but i had no luck.
{
public float speed = 0.5f;
public Vector3 castlePosition;
private Vector3 targetPosition;
// Start is called before the first frame update
void Start()
{
targetPosition = transform.position;
}
// Update is called once per frame
void Update()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit))
{
if(hit.transform.GetComponent<DoorButton>() != null)
{
hit.transform.GetComponent<DoorButton>().OnLook();
MoveToCastle ();
}
}
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * speed);
}
private void MoveToCastle()
{
targetPosition = castlePosition;
}
}
I was expecting that the MoveToCastle function would put my player inside the castle (at the position that I declared earlier).
Once again the OnLook function from my door is working.
Thank you in advance for your help. :)
Your MoveToCastle stops working as soon as raycast becomes false. You probably should set off some continuous process of moving to target when the raycast hits. For example start coroutine something like this:
IEnumerable MoveToCastle()
{
targetPosition = castlePosition;
while (transform.position != castlePosition) // careful here! see below
{
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * speed);
yield return null;
}
}
Better to compare target and transform coordinates by subtracting and comparing to some small value, otherwise it can go there quite long.
Related
I have a weird problem and cant seem to fix it. I was creating my first game in Unity and I was testing around a bit after creating a movement system and whenever I touch another object (it doesn't matter if it has a rigid body or not), my player suddenly starts moving on its own. I have a video showing what exactly happens: https://youtu.be/WGrJ0KNYSr4
I have tried a few different things already and I determined that it has to do something with the physics engine because it only happens when the player isn't kinematic. So, I tried to increase the solver iterations for physics in the project settings, but the bug was still happening. I looked for answers on the internet, yet the only thing I found was to remove Time.deltaTime, though it still doesn't work. I have found that it seems to happen less though when the player is moving fast.
I would really appreciate if somebody could help me with this. This is my first real game and I'm creating it for the Seajam that's happening on itch.io.
Here is the code for my playercontroller script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float playerSpeed = 3f;
private Rigidbody playerRb;
public GameObject cameraRotation;
// Start is called before the first frame update
void Start()
{
playerRb = GetComponent<Rigidbody>();
}
float verticalSpeed;
float horizontalSpeed;
bool isOnGround = true;
// Update is called once per frame
void Update()
{
//get controlled forward and backward motion
verticalSpeed = Input.GetAxis("Vertical");
transform.Translate(Vector3.forward * playerSpeed * verticalSpeed * Time.deltaTime);
//get controlled sidewards motion
horizontalSpeed = Input.GetAxis("Horizontal");
transform.Translate(Vector3.right * playerSpeed * horizontalSpeed * Time.deltaTime);
//lock the rotation of the player on the z and x axis
transform.eulerAngles = new Vector3(0, cameraRotation.transform.eulerAngles.y, 0);
//when pressing space jump and prevent air jump
if (Input.GetKeyDown(KeyCode.Space) && isOnGround)
{
playerRb.AddForce(Vector3.up * 10, ForceMode.Impulse);
isOnGround = false;
}
}
//check if the player is on the ground
private void OnCollisionEnter(Collision collision)
{
isOnGround = true;
}
}
Try not locking the player's rotation by script, maybe it is causing the problem due to gimbal lock. Instead go to your player's RigidBody->Constraints and then lock it.
You can read more about it here https://fr.wikipedia.org/wiki/Blocage_de_cardan
So my game is sort of like a 3d top down shooter, so I want my gun to shoot wherever the mouse is and it wont go to the mouse unless im shooting down. If you've seen brackyes game called ball wars, im sort of trying to replicate one like that but the projectile is not shooting the right way.
I got my script from blackthornprods ranged combat tutorial (which is for 2d so maybe thats the issue but I dont know how to solve it) :
public float speed;
public float lifeTime;
private void Start()
{
Invoke("DestoryProjectile", lifeTime);
}
private void Update()
{
transform.Translate(transform.up * speed * Time.deltaTime);
}
void DestroyProjectile()
{
Destroy(gameObject);
}
Appreciate anyone to try!
Here is my other script:
Camera mainCam;
public GameObject projectile;
public Transform shotPoint;
private float timeBtwShots;
public float startTimeBtwShots;
void Awake()
{
mainCam = Camera.main;
}
void Update()
{
float objectDepthFromCamera = Vector3.Dot(
transform.position - mainCam.transform.position,
mainCam.transform.forward);
Vector3 cursorWorldPosition = mainCam.ScreenToWorldPoint(Input.mousePosition
+ Vector3.forward * objectDepthFromCamera);
Vector3 localUpNeeded = Vector3.Cross(Vector3.forward,
cursorWorldPosition - transform.position);
transform.rotation = Quaternion.LookRotation(Vector3.forward, localUpNeeded);
if(timeBtwShots <= 0)
{
if (Input.GetMouseButtonDown(0))
{
Instantiate(projectile, shotPoint.position, transform.rotation);
timeBtwShots = startTimeBtwShots;
}
}
else
{
timeBtwShots -= Time.deltaTime;
}
}
Projectile not shooting direction of my weapon. Simple solution -
First instantiate or pool the instance of projectile.
Set rotation of projection from the rotation of weapon & set location to spawn point
Now fire, or whatever strategy you are using
Consider Global rotation, if you need help, tell me, I will edit and give a snippet of code.
This should work. If doesn't post all necessary code, I will give a better solution.
Here is sample github project I created, just for you. I opened Unity nearly after a year. Please check all the versions.
Must check :
firing in facing direction 💋
just instantiate at spawn point
just added some rotation
I think this should give you concept.
Press X for a rantom rotation
Press Space to shoot a projectile :lol:
The white cube shows that it always shoots at a constant direction
I'm new to Unity, so probably this is a dumb question but I have several days trying to figure it out. I have an enemy walking from one side of a platform to the other. I'm using Raycasting to check if there´s no ground below and turn to the other way.
What I want is for the enemy to walk AROUND the platform (Just like the enemies in Metroid). I set the gravity of the enemy to 0 so it will not fall down, but I don´t know how to make it rotate and keep walking around the platform. I know it could be done with raycasting but I have not clue how to do it.
I will enormously appreciated if anyone can help me with the piece of code I'm missing. Thanks in advance!
public class BlobController : MonoBehaviour {
private Rigidbody2D myRigidBody;
public float moveSpeed;
public LayerMask groundMask;
float myWidth;
// Use this for initialization
void Start ()
{
myRigidBody = GetComponent<Rigidbody2D>();
myWidth = GetComponent<SpriteRenderer> ().bounds.extents.x;
}
// Update is called once per frame
void Update ()
{
}
void FixedUpdate()
{
//Check to see if there's ground in front before moving forward
Vector2 lineCasPos = transform.position - transform.right * myWidth;
Debug.DrawRay (lineCasPos, Vector2.down,Color.red);
bool isGrounded = Physics2D.Raycast (lineCasPos, Vector2.down, 2, groundMask);
//If there's no ground, turn around
if (!isGrounded)
{
Vector3 currRot = transform.eulerAngles;
currRot.y += 180;
transform.eulerAngles = currRot;
}
//Always move forward
Vector2 myVel = myRigidBody.velocity;
myVel.x = -transform.right.x * moveSpeed;
myRigidBody.velocity = myVel;
}
}
I have the following code
public Rigidbody2D rb;
public float speed = 5f;
void FixedUpdate()
{
if (Input.GetKeyDown("w"))
{
Fire();
}
}
void Fire()
{
rb.MovePosition(rb.position + Vector2.down * speed * Time.deltaTime);
}
but every time I play the game, the ball does not move according to the fire function, it only goes down by 1 on the y-axis.
How can I edit my code, so that the Rigidbody moves according to the Fire() function?
There could be a couple things going wrong here. The first thing that stands out to me is that you're using Input.GetKeyDown instead of Input.GetKey-- GetKeyDown only returns true on the first frame that the key is pressed (so it's useful for things like shooting once per keypress), whereas GetKey returns true for the entire time that the key is down (so it's useful for things like movement). Changing that should give you the behavior that you're expecting.
Another issue is that you're doing input checking in FixedUpdate. It runs on a separate game loop from Update, and you can find more details about that here: Is it really wrong to use Input.GetKey() on FixedUpdate?
I would use Input and GetKey to store the input state in a Vector2 in the Update loop, and then use that data in FixedUpdate to do the actual movement:
public Rigidbody2D rb;
public float speed = 5f;
private Vector2 velocity = Vector2.zero;
void Update()
{
if (Input.GetKey("w"))
{
velocity = Vector2.down * speed;
}
else {
velocity = Vector2.zero;
}
}
void FixedUpdate()
{
MoveBall();
}
void MoveBall()
{
rb.MovePosition(rb.position * velocity * Time.deltaTime);
}
This way, you also have a stronger separation between the input code and movement code, and it will be easier to handle once you start trying to implement more complexity. Good luck!
Okay so I've been fighting with this script for a couple days now. I've made progress in other aspects but I can't seem to get my enemies to properly chase the player character.
The script is supposed to have the enemies wander until an empty child 'eyes' sees the player. Then it should start chasing the player. Think pac-man. What it's doing right now is making one loop of it's wander cycle and then stopping and not seeing the player at all.
This is the code that I've got so far for that script -
using UnityEngine;
using System.Collections;
public class dudeFollow : MonoBehaviour {
Transform tr_Player;
float f_MoveSpeed = 3.0f;
private DudeMove moveScript;
public Transform eyes;
public float sightRange = 3f;
// Use this for initialization
void Start () {
tr_Player = GameObject.FindGameObjectWithTag("Player").transform;
moveScript = GetComponent<DudeMove>();
}
// Update is called once per frame
void Update () {
RaycastHit hit;
if (Physics.Raycast (eyes.transform.position,eyes.transform.forward, out hit,sightRange) && hit.collider.CompareTag ("Player")) {
transform.position += transform.forward * f_MoveSpeed * Time.deltaTime;
moveScript.enabled = false;
}
}
}
Any help or tips would be appreciated.
Because you have 2D game, what most likely happens is your enemy wonders away on z-axis as well, but because it's 2D, you can't see it. So switch to 3D mode in your main scene window and see if that's the case.
If it is, just reset z-axis to 0 on every frame and disable angular momentum :) I had this happen with 2D games.
void Update () {
RaycastHit hit;
if (Physics.Raycast (eyes.transform.position,eyes.transform.forward, out hit,sightRange) && hit.collider.CompareTag ("Player")) {
transform.position += transform.forward * f_MoveSpeed * Time.deltaTime;
moveScript.enabled = false;
}
transform.position.z = 0; // or something along those lines, I don't remember the syntax exactly.
}