Issue with Player Movement Unity - c#

I am VERY new to unity and I wrote this very basic program to move the player. This program works when there is no conditional statement on if the w key is pressed, but if you add it, the capsule is unable to move.
if (Input.GetKeyDown("w"))
{
Vector3 cameraForward = Camera.main.transform.forward;
cameraForward.y = 0;
cameraForward = cameraForward.normalized;
Vector3 moveDirection = cameraForward * speed * Time.deltaTime;
transform.position += moveDirection;
}
The only issue I can see with this is that the capsule is clipping into the plain, although I have a collider and a rigidbody on it. If you run this the capsule just does not move, at all. If it at all matters, I also have another line of code that sets the rotation of the capsule to 0, 0, 0, 0 every frame.

Input.GetKeyDown() only triggers once per key-press. Your biggest issue (there may be others) is that that will only move the player forward for a single tick. You want Input.GetKey() (Unity Docs) instead.

Related

Unity3D c# 2D Game Camera Follow is making jumps

I made an 2D endless runner game using Unity, where the Player Object moves upwards, but for the Viewer he remains on the same spot because the Camera is following him. The Following works pretty well, but the problem is that it is making small jumps every few seconds. The jumps are small and thus are not affecting the gameplay in general but they are big enough to make it seem like the game is not running smoothly.
I can't even tell whether it is the Camera that is making the jumps or the Player Object. But I think it is the Camera, because the spawning obstacles are also making jumps. What may be the issue? Am I using the right method for the Camera?
public class Player
{
float speed = 5f;
void Update()
{
transform.Translate(0, speed*Time.deltaTime, 0);
}
}
And this is the Script which is attached to the Camera:
public class CameraFollow
{
private Vector3 FollowVector;
public Transform Player;
void LadeUpdate()
{
FollowVector = Player.position - new Vector3(0, -4f, 10);
transform.position = Vector3.Lerp(transform.position, FollowVector, Time.deltaTime * 4f);
}
}
Does the jump happen every 4 seconds? I think the problem might be in your Vector3.Lerp function. It's basically a loose camera-follow, that takes 4 seconds (Time.deltaTime * 4f) to smoothly go from Point A to point B. Every 4 seconds it resets its path, hence the hop. At least that's my theory.
If you don't mind the camera rigidly following the player, I would just remove the Lerp and just set the transform.position to be the FollowVector value like so:
void LadeUpdate()
{
transform.position = Player.position - new Vector3(0, -4f, 10);
}
Try to use Vector3.MoveTowards
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, Player.position - new Vector3(0, -4f, 10f), step);

Rigidbody behaves differently when I select another gameobject in the scene

This the strangest thing i ever saw, i swear! So i have a script to the player that when you click on screen the cube jumps in the direction of the arrow(the arrow rotates 360 degres).I changed some settings to the rigidbody2d to make the jump better.Now here comes the strange part,when i run the game and the player is selected in the scene or hierrachy the jump works fine,if i select something else for exemple the camera something chenges the jump,from a very good one to a very bad one,i tryed to build the project and test and is the same,the cube dosen't have the same "Jump".I think it's becouse i changed something in the rigidbody,idk.PLS HELP!!!center
P.S if u ask for the script here it is :
public void Update()
{
Lava.transform.position = new Vector2(transform.position.x, Lava.transform.position.y);//other,not important
cam.transform.position = transform.position + offset;//camera follow player
Arrow.transform.RotateAround(gameObject.transform.position, new Vector3(0, 0, 180), ArrowSpeed * Time.deltaTime); //to make the arrow rotate 360
if (Input.GetMouseButtonDown(0))
{
rb.AddForce(Arrow.transform.right * -ImpulseForce * Time.deltaTime, ForceMode2D.Impulse); //this makes the cube jump
}
//other
score = (int) transform.position.y;
ScoreUI.text = score.ToString();
}
Firstly, RotateAround method takes a normalized vector as its second parameter, such as Vector3.forward in your case.
Secondly, applying any force to a rigidbody should be done in FixedUpdate, not Update (see Rigidbody.AddForce and ForceMode)
In your case it's an impulse, and it's only called when you click, so no need to multiply by delta time.
rb.AddForce(Arrow.transform.right * -ImpulseForce, ForceMode2D.Impulse);
It may not solve all of your issues, but without further information it's tough to know. At least you wont have weird physics behaviors anymore.

Adapting player behaviour to AI in unity

I have designed an attack method for a player that is full functional, however I am new to AI and have no idea as to where I would begin when it comes to adapting this into a state for an FSM.
protected void UpdateAttackState()
{
// check for input
float rot = transform.localEulerAngles.y + rotationSpeed * Time.deltaTime * Input.GetAxis("Horizontal");
Vector3 fwd = transform.forward * moveSpeed * Time.deltaTime * Input.GetAxis("Vertical");
// Tank Chassis is rigidbody, use MoveRotation and MovePosition
GetComponent<Rigidbody>().MoveRotation(Quaternion.AngleAxis(rot, Vector3.up));
GetComponent<Rigidbody>().MovePosition(_rigidbody.position + fwd);
if (turret) {
Plane playerPlane = new Plane(Vector3.up, transform.position + new Vector3(0, 0, 0));
// Generate a ray from the cursor position
Ray RayCast = Camera.main.ScreenPointToRay(Input.mousePosition);
// Determine the point where the cursor ray intersects the plane.
float HitDist = 0;
// If the ray is parallel to the plane, Raycast will return false.
if (playerPlane.Raycast(RayCast, out HitDist))
{
// Get the point along the ray that hits the calculated distance.
Vector3 RayHitPoint = RayCast.GetPoint(HitDist);
Quaternion targetRotation = Quaternion.LookRotation(RayHitPoint - transform.position);
turret.transform.rotation = Quaternion.Slerp(turret.transform.rotation, targetRotation, Time.deltaTime* turretRotSpeed);
}
}
if(Input.GetButton("Fire1"))
{
if (elapsedTime >= shootRate)
{
//Reset the time
elapsedTime = 0.0f;
//Also Instantiate over the PhotonNetwork
if ((bulletSpawnPoint) & (bullet))
Instantiate(bullet, bulletSpawnPoint.transform.position, bulletSpawnPoint.transform.rotation);
}
}
// Update the time
elapsedTime += Time.deltaTime;
}
This is completely dependent on how you want your state machine to work. An example of this would be the AI trying to seek and destroy other players.
Seeking State: AI would move around the map with a detection zone (collider) that would change state on trigger enter. This would then save a position of the detection's generalized location which would be used to move and rotate the AI tank towards that position.
Firing State: AI enters a new detection zone (collider) within firing range, turret will move to aim at target. AI will also move around the map to keep firing range at a maximum while also keeping track of the last known position of the enemy if they happen to go out of range.
Detecting Fire: Player or other AI fires their weapon this could increase the detection radius resulting in a seeking state being called.
After those functions are figured out, place a switch or something similar within the Update() to allow everything within the AI to run alongside Unity's functions.

Instantiate a prefab pointing in the direction of another object

The Issue
I'm making a 2D Unity game where the main weapon of your character is a fireball gun. The idea is that a fireball will shoot out of the player's hand at the same angle the player's hand is pointing. I have 3 issues:
When I shoot the fireball, since the fireball is a RididBody, it pushes the player. This is because I've made the centre of the player's arm (the same place where the fireball shoots from) the point at which the arm rotates around the player (what is meant to be the shoulder);
To instantiate the fireball prefab on the arm, the only way I know how to do it is by using a piece of code which requires the arm to be a RigidBody. This means that the arm is affected by gravity and falls off the player on start unless I freeze the arm's y-axis movement, which means that when the player jumps, while the arm does not fall, it floats at the same y-position as where it started while moving along the x-axis; and
When the fireball is shot, the angle from which it is propelled after being shot is not the same angle as the angle of the player's arm.
Instantiating the Fireball
if (Input.GetKeyDown(KeyCode.Space))
{
pew.Play();
var fireballTransform = Instantiate(fireballPrefab); //creates a new shot sprite
fireballTransform.position = new Vector3(transform.position.x + horizMultiplier, transform.position.y, transform.position.z);
fireballTransform.rotation = orientation;
fireballTransform.transform.Rotate(0, 0, transform.rotation.z);
}
if (Input.GetKeyDown(KeyCode.D)) // moves right
{
orientation = 0;
horizMultiplier = 0.08F;
}
if (Input.GetKeyDown(KeyCode.A)) // moves left
{
orientation = 180;
horizMultiplier = -0.08F;
}
This piece of code is located within the script applied to the player's arm. The movement of the arm works fine and the problem seems to be either within this piece of code or the code for my fireball (which I will put next). A few definitions:
pew is a sound effect played when the fireball is shot;
horizMultiplier is the distance from the arm's centre which I would like the fireball to instantiate (also dependant of if the player) is facing left or right); and
orientation is which direction the player is facing (left or right). The fireball is then instantiated facing that same direction.
Fireball Script
public Vector2 speed = new Vector2(); // x and y forces respectively
private Rigidbody2D rb; // shorthand
private float rotation;
void Start()
{
rb = GetComponent<Rigidbody2D>(); // shorthand
rotation = rb.rotation;
if (rotation == 0)
{
rb.AddForce(Vector3.right * speed.x); // propels right
}
if (rotation == 180)
{
rb.AddForce(Vector3.left * speed.x); // propels left
}
}
I believe this code is explanatory enough with comments (if not please comment and I'll address any question). I believe an issue could also be in this piece of code because of the lines: rb.AddForce(Vector3.right * speed.x); and rb.AddForce(Vector3.left * speed.x); as these add directional forces to the object. I don't know is this is objective direction (right or left no matter what direction the object the force is being applied to is facing) or if it's right or left in terms of the object-- say if an object was rotated 90 degrees clockwise and that object had a force applied so that it moves right making the object move downwards.
What I'm expecting to happen is the player's arm will turn so that when a fireball is fired it is fired in the direction the arm is facing. The arms turning mechanics are fine, it's just trying to properly instantiate the fireball. Can anyone help with any of the issues I've laid out?
How I would go about this:
Add an empty transform as child of the arm and move it to where the fireball should spawn. Also make sure the rotation of it is such that its forward vector (the local z-axis) points to where the fireball should go. To see this, you need to set "Local" left of the play button.
Spawn the fireball at the transform's position with its rotation.
Ignore collision between the arm's/player's collider and the fireball's collider with https://docs.unity3d.com/ScriptReference/Physics.IgnoreCollision.html. If necessary, you can enable the collision between the two colliders again after 1s or so.
Set the fireball rigidbody's velocity to speed * rigidbody.forward.
If you need help with the code, please post it so I can see what's going on.
Edit:
The arm definitely doesn't require a Rigidbody.
You can just use Instantiate(prefab, position, rotation) as shorthand.
Is this for a 2D game?
Also, I'm going to sleep now but I'll gladly try to help tomorrow.
Your Issues
1) You should be masking the fireball's layer not to collide with your player's layer.
You can find more info about this here: https://docs.unity3d.com/Manual/LayerBasedCollision.html
(note: make sure you're on the Physics2D panel, and not the Physics one, as that's for 3D)
2) There is a setting called gravityScale in RigidBody2D. You should set this to 0 if you don't want gravity to be affecting your object. More info: https://docs.unity3d.com/Manual/class-Rigidbody2D.html
Fireball Instantiate
if (Input.GetKeyDown(KeyCode.Space))
{
pew.Play();
var position = hand.transform.position + hand.transform.forward * horizMultiplier;
var rotation = hand.transform.rotation;
var fireball = Instantiate<Fireball>(fireballPrefab, position, rotation);
fireball.StartMoving();
}
Fireball Script
private Rigidbody2D rb; // shorthand
private float rotation;
public float Speed;
public void StartMoving()
{
rb = GetComponent<Rigidbody2D>(); // shorthand
rb.velocity = transform.forward * Speed;
}
void OnTriggerEnter(....) { .... }

Unity 2D C# - Collider not working

I am working on a 2D TopDown game in Unity 5. The collision is not working at all.
The player and the obstacle both have a 2D Collider and they are not Trigger. The player has a 2D Rigidbody with Kinematic set to false, gravity scale is equal to zero. Maybe the movement code has something to do with it.
The code is a bit long so I'll just show you the code for moving up:
if (Input.GetAxis ("Up") > 0) {
if (movingDown == false) {
posY += speed * Time.deltaTime;
movingUp = true;
}
} else {
movingUp = false;
}
/.../
transform.position = new Vector3 (posX, posY, 0);
It is always setting the value of the position as long as you are pressing the up button. Is there a way to fix this?
I think that the problem is that you are setting the position directly. So at each frame, you are telling unity exactly were the object should be, which overrides the position that would be computed from collision.
To fix this, you need to modify your movement code to add a force to your rigidbody and leave the position untouched ( see rigidbody doc, and function AddForce (https://docs.unity3d.com/ScriptReference/Rigidbody.html)
Try using
rb.velocity = new Vector3 (rb.velocity.x, rb.velocity.y, ConstantZValue);
This replaces your system with a velocity-based system as updating the transform.postition of a rigidbody is not recommended. With the system you have, the collision is not being detected because the rigidbody isn't being updated.

Categories