I have written a code to get a random transform from my list pathPoints and move my object based on that transform, but what it is doing is getting multiple transforms and trying to move everywhere at once. I want the object to move at one position then get a new position and move there then repeat.
Here is the code:-
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PathFinder : MonoBehaviour
[SerializeField] List<Transform> pathPoints;
[SerializeField] Transform pathPrefab;
[SerializeField] float moveSpeed = 10f;
[SerializeField] bool isMoving = false;
[SerializeField] bool isH_Attacking = false;
Animator anim;
Transform defaultWayPoint;
Transform currentTargetPoint;
void Awake()
{
anim = GetComponent<Animator>();
defaultWayPoint = pathPrefab.GetChild(0);
}
void Start()
{
currentTargetPoint = pathPoints[Random.Range(0, pathPoints.Count)];
transform.position = defaultWayPoint.position;
}
void MoveToNextWayPoint()
{
if(transform.position != currentTargetPoint.position)
{
float delta = moveSpeed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, currentTargetPoint.position, delta);
anim.SetBool("isMoving", true);
isMoving = true;
}
GetNextWayPoint();
}
Transform GetNextWayPoint()
{
currentTargetPoint = pathPoints[Random.Range(0, pathPoints.Count)];
Debug.Log(currentTargetPoint.position);
return currentTargetPoint;
}
void Update()
{
MoveToNextWayPoint();
}
*The script is attached to the gameObject which I want to move.
*This is a 2d project.
void MoveToNextWayPoint()
{
if(transform.position != currentTargetPoint.position)
{
float delta = moveSpeed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, currentTargetPoint.position, delta);
anim.SetBool("isMoving", true);
isMoving = true;
}
else
{
GetNextWayPoint();
}
}
Related
I'm creating a 2D Top Down game for practice and I need a little bit of help. For context, it's a 2D Top Down Shooter game, where you can move and shoot enemies. The enemies have a basic radius system where if the player gets within the radius, it'll approach the player.
Now I'm making a game mechanic where the player can hide in a cardboard box, the player can press 'E' and he'll suddenly become a cardboard box, where if the player is in the cardboard box, the enemy doesn't detect him even if the player's within the radius. Yes, just like in Metal Gear. Now I've created the prefabs and everything and functionality-wise, it works perfectly. If you press 'E' the enemy cannot detect you.
Now the small problem is that the cardboard box didn't appear, so it's just the player disappearing entirely. I do not know what caused this problem.
For context, these are my scripts. Feel free to read them, or not :)
PlayerController:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public GameObject bulletPrefab;
public GameObject player;
private Rigidbody2D rb2d;
private Vector2 moveDirection;
[SerializeField] private Camera cam;
[SerializeField] private GameObject gunPoint;
public bool isHiding = false;
[SerializeField] private GameObject cardboardBox;
[SerializeField] private GameObject gunSprite;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
cardboardBox.SetActive(false); // Hide the cardboard box when the game starts
gunSprite.SetActive(true); // Show the gun sprite when the game starts
}
// Update is called once per frame
void Update()
{
CheckCursor();
ProcessInputs();
// Make the camera follow the player
cam.transform.position = new Vector3(player.transform.position.x, player.transform.position.y, cam.transform.position.z);
// Check if player pressed the "E" key to toggle the cardboard box
if (Input.GetKeyDown(KeyCode.E))
{
isHiding = !isHiding; // Toggle the isHiding variable
cardboardBox.SetActive(isHiding); // Show/hide the cardboard box accordingly
// If player is hiding, stop player movement
if (isHiding)
{
moveDirection = Vector2.zero;
player.GetComponent<SpriteRenderer>().enabled = false;
cardboardBox.GetComponent<SpriteRenderer>().enabled = true;
gunSprite.SetActive(false); // Hide the gun sprite when the player is hiding
}
else
{
player.GetComponent<SpriteRenderer>().enabled = true;
cardboardBox.GetComponent<SpriteRenderer>().enabled = false;
gunSprite.SetActive(true); // Show the gun sprite when the player is not hiding
}
}
}
private void FixedUpdate()
{
if (!isHiding) // Only allow player to move if they are not hiding in the cardboard box
{
Movement();
}
}
private void CheckCursor()
{
Vector3 mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
Vector3 characterPos = transform.position;
if (mousePos.x > characterPos.x)
{
this.transform.rotation = new Quaternion(0, 0, 0, 0);
}
else if (mousePos.x < characterPos.x)
{
this.transform.rotation = new Quaternion(0, 180, 0, 0);
}
}
private void Movement()
{
// TODO : Implementasi movement player
rb2d.velocity = new Vector2(moveDirection.x * moveSpeed, moveDirection.y * moveSpeed);
}
private void ProcessInputs()
{
float moveX = Input.GetAxisRaw("Horizontal");
float moveY = Input.GetAxisRaw("Vertical");
moveDirection = new Vector2(moveX, moveY);
if (Input.GetMouseButtonDown(0))
{
Shoot();
}
}
private void Shoot()
{
Vector3 mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
Vector3 gunPointPos = gunPoint.transform.position;
Vector3 direction = (mousePos - gunPointPos).normalized;
GameObject bullet = Instantiate(bulletPrefab, gunPointPos, Quaternion.identity);
bullet.GetComponent<Bullet>().Init(direction);
}
}
EnemyController script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyController : MonoBehaviour
{
public Transform player;
public float moveSpeed = 5f;
public float detectionRadius = 5f;
public int maxHealth = 1;
private int currentHealth;
private Rigidbody2D rb2d;
private Vector2 movement;
private void Start()
{
rb2d = this.GetComponent<Rigidbody2D>();
currentHealth = maxHealth;
}
private void Update()
{
float distanceToPlayer = Vector2.Distance(transform.position, player.position);
if (player != null && distanceToPlayer <= detectionRadius && !player.GetComponent<PlayerController>().isHiding)
{
Vector3 direction = player.position - transform.position;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
rb2d.rotation = angle;
direction.Normalize();
movement = direction;
}
else
{
movement = Vector2.zero;
}
}
void FixedUpdate()
{
moveCharacter(movement);
}
private void moveCharacter(Vector2 direction)
{
rb2d.MovePosition((Vector2)transform.position + (direction * moveSpeed * Time.deltaTime));
}
public void DestroyEnemy()
{
Destroy(gameObject);
}
}
Bullet script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
// Start is called before the first frame update
[SerializeField] private float speed;
[SerializeField] private Vector3 direction;
public void Init(Vector3 direction)
{
this.direction = direction;
this.transform.SetParent(null);
transform.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg);
}
// Update is called once per frame
void Update()
{
this.transform.position += transform.right * speed * Time.deltaTime;
}
// TODO : Implementasi behaviour bullet jika mengenai wall atau enemy
private void OnTriggerEnter2D(Collider2D other)
{
switch(other.gameObject.tag)
{
case "Wall":
Destroy(gameObject);
break;
case "Enemy":
Destroy(gameObject);
other.gameObject.GetComponent<EnemyController>().DestroyEnemy();
break;
}
}
}
I've tried tinkering my scripts, I've tried checking if there are any missing components in the cardboard box game object but to no avail. Although I might be wrong on the Unity part since I'm fairly certain that the script isn't the problem here, again might be wrong.
I appreciate all the help I can get, thank you for reading until here
I'm making a platformer controller using the new Input System and trying to control the curve for jumping... I've figured out how to add a damp for the horizontal movement which give the horizonal movement a bit of a slippery feel. But I cannot figure out how to control curve for the Jump. The problem now is I'm using a Player Input Component and Unity Events to control the Move and Jump. And the jump is using rb.velocity.y.
How do I control my Jump curve?
Here is the current curve:
I want to controle the acceleration and deacceleration of the curve:
Here is the curve I'd like to achieve with jumping
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerMovement : MonoBehaviour
{
private const float GroundedRadius = 0.2f;
[SerializeField] private float smoothInputSpeed = .2f;
[SerializeField] private float speed = 8f;
[SerializeField] private float jumpingPower = 12f;
[SerializeField] private float fallPower = 2f;
[SerializeField] private Rigidbody2D rb;
[SerializeField] private Transform groundCheck;
[SerializeField] private LayerMask groundLayer;
private Vector2 _smoothMove = Vector2.zero;
private Vector2 _smoothInputVelocity = Vector2.zero;
private Vector2 _move = Vector2.zero;
private bool _isFacingRight = true;
void Update()
{
_smoothMove = Vector2.SmoothDamp(_smoothMove, _move, ref _smoothInputVelocity, smoothInputSpeed);
rb.velocity = new Vector2(_smoothMove.x * speed, rb.velocity.y);
if (!_isFacingRight && _move.x > 0f || _isFacingRight && _move.x < 0f)
{
Flip();
}
}
public void Move(InputAction.CallbackContext context)
{
_move = context.ReadValue<Vector2>();
}
public void Jump(InputAction.CallbackContext context)
{
if (context.performed && IsGrounded())
{
rb.velocity = new Vector2(rb.velocity.x, jumpingPower);
}
if (context.canceled && rb.velocity.y > 0f)
{
var velocity = rb.velocity;
var gravity = rb.gravityScale;
velocity = new Vector2(velocity.x, (velocity.y * gravity * fallPower)); // fall faster if cancelled
rb.velocity -= velocity;
}
}
private bool IsGrounded()
{
return Physics2D.OverlapCircle(groundCheck.position, GroundedRadius, groundLayer);
}
private void Flip()
{
_isFacingRight = !_isFacingRight;
var transform1 = transform;
Vector3 localScale = transform1.localScale;
localScale.x *= -1f;
transform1.localScale = localScale;
}
}
This is my player movement code:
Footage of bug and inspector elements:
https://imgur.com/a/bmGqL1M
As you can see in this Imgur video, for some reason my player character, and also a pushable crate, can clip into this tilemap for a few pixels. I'm not quite sure why this is happening, since I've added a composite collider2D to the tilemap, to get rid of the very common "getting stuck in tilemap" bug, which isn't the case here, the clipping doesn't actually alter the movement in any way.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[Header("Movement")]
[SerializeField] private float movementSpeed;
[SerializeField] private float jumpForce;
[Header("Jumping")]
private bool isGrounded;
[SerializeField] private Transform feetPos;
[SerializeField] private float checkRadius;
[SerializeField] private LayerMask whatIsGround;
[SerializeField] private float hangTime;
private float hangCounter;
private Rigidbody2D rb;
private SpriteRenderer sr;
private float moveX;
void Start()
{
rb = GetComponent<Rigidbody2D>();
sr = GetComponent<SpriteRenderer>();
}
void Update()
{
GetInput();
BetterJump();
}
void BetterJump()
{
isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);
if (isGrounded)
{
hangCounter = hangTime;
} else
{
hangCounter -= Time.deltaTime;
}
if (hangCounter > 0 && Input.GetKeyDown(KeyCode.Space))
{
rb.velocity = Vector2.up * jumpForce;
}
if (Input.GetButtonUp("Jump") && rb.velocity.y > 0)
{
rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * .5f);
}
}
void FixedUpdate()
{
Move();
}
void Move()
{
rb.position += new Vector2(moveX, 0) * Time.deltaTime * movementSpeed;
}
void GetInput()
{
moveX = Input.GetAxisRaw("Horizontal");
if(moveX < 0)
{
sr.flipX = true;
}
else if (moveX > 0)
{
sr.flipX = false;
}
}
}
I have both player and ground with colliders 2D and player is supposed to stop on top of ground but instead it stops at the bottom of the ground.
Code
PlayerController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
private float moveSpeedStore;
public float speedMultiplier;
public float speedIncreateMilestone;
private float speedIncreateMilestoneStore;
private float speedMilestoneCount;
private float speedMilestoneCountStore;
public float jumpForce;
public float jumpTime;
private float jumpTimeCounter;
private bool stoppedJumping;
private bool canDoubleJump;
private Rigidbody2D myRigidbody;
public bool grounded;
public LayerMask whatIsGround;
public Transform groundCheck;
public float groundCheckRadius;
// private Collider2D myCollider;
private Animator myAnimator;
public GameManager theGameManager;
public AudioSource jumpSound;
public AudioSource deathSound;
// Start is called before the first frame update
void Start()
{
myRigidbody = GetComponent<Rigidbody2D>();
myAnimator = GetComponent<Animator>();
jumpTimeCounter = jumpTime;
speedMilestoneCount = speedIncreateMilestone;
moveSpeedStore = moveSpeed;
speedMilestoneCountStore = speedMilestoneCount;
speedIncreateMilestoneStore = speedIncreateMilestone;
stoppedJumping = true;
}
// Update is called once per frame
void Update()
{
grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
if(transform.position.x > speedMilestoneCount)
{
speedMilestoneCount += speedIncreateMilestone;
speedIncreateMilestone = speedIncreateMilestone * speedMultiplier;
moveSpeed = moveSpeed * speedMultiplier;
}
myRigidbody.velocity = new Vector2(moveSpeed, myRigidbody.velocity.y);
if(Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0) )
{
if(grounded)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x, jumpForce);
stoppedJumping = false;
jumpSound.Play();
}
if(!grounded && canDoubleJump)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x, jumpForce);
jumpTimeCounter = jumpTime;
stoppedJumping = false;
canDoubleJump = false;
jumpSound.Play();
}
}
if((Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0)) && !stoppedJumping)
{
if(jumpTimeCounter > 0)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x, jumpForce);
jumpTimeCounter -= Time.deltaTime;
}
}
if(Input.GetKeyUp(KeyCode.Space) || Input.GetMouseButtonUp(0))
{
jumpTimeCounter = 0;
stoppedJumping = true;
}
if(grounded)
{
jumpTimeCounter = jumpTime;
canDoubleJump = true;
}
myAnimator.SetFloat("Speed", myRigidbody.velocity.x);
myAnimator.SetBool("Grounded", grounded);
}
void OnCollisionEnter2D(Collision2D other) {
if(other.gameObject.tag == "killbox")
{
theGameManager.RestartGame();
moveSpeed = moveSpeedStore;
speedMilestoneCount = speedMilestoneCountStore;
speedIncreateMilestone = speedIncreateMilestoneStore;
deathSound.Play();
}
}
}
Player settings
Question
What should I do to hold my player on top of ground?
NOTE: it's my first question on unity ever so if you need any sort of code or data please just ask, I try my best to provide you what you need.
Thanks.
It looks like your collider is simply too high. You'll notice that the green box indicating your collider size and position is colliding with the correct spot on the ground. The bottom of it is just touching the top of the ground. You simply need to move the collider down on the player so that the bottom of the green box is at the bottom of the player's sprite.
This is my code does anyone know or can anyone spot why my projectile remains stationary once it's spawned in? the projectile is the prefab shell thanks for your help in advance.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TankBehaviour : MonoBehaviour
{
public GameObject shellPrefab;
public Transform fireTransform;
private bool isFired = false;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
float x = Input.GetAxis("Horizontal");
float y = Input.GetAxis("Vertical");
transform.position += transform.forward * y;
transform.Rotate(0, x, 0);
if (Input.GetKeyUp(KeyCode.Space) && !isFired)
{
Debug.Log("fire!");
Fire();
}
}
void Fire()
{
//isFired = true;
GameObject shellInstance = Instantiate(shellPrefab,
fireTransform.position,
fireTransform.rotation) as GameObject;
if (shellInstance)
{
shellInstance.tag = "Shell";
Rigidbody shellRB = shellInstance.GetComponent<Rigidbody>();
shellRB.velocity = 15.0f * fireTransform.forward;
Debug.Log("velocity");
}
}
}
It is also generally discouraged to set the velocity of a rigidbody, but you can use the Rigidbody.AddForce() method to add force to a rigidbody. When you just want add force at the start, you can set the force mode in the function to impulse, like this rb.AddForce(Vector3.forward, ForceMode2D.Impulse);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TankBehaviour : MonoBehaviour
{
public GameObject shellPrefab;
public Transform fireTransform;
private bool isFired = false;
public float bulletSpeed;
void Update()
{
float x = Input.GetAxis("Horizontal");
float y = Input.GetAxis("Vertical");
transform.position += transform.forward * y;
transform.Rotate(0, x, 0);
if (Input.GetKeyUp(KeyCode.Space) && !isFired)
{
Debug.Log("fire!");
Fire();
}
}
void Fire()
{
//isFired = true;
GameObject shellInstance = Instantiate(shellPrefab, fireTransform.position, fireTransform.rotation) as GameObject;
if (shellInstance)
{
shellInstance.tag = "Shell";
Rigidbody shellRB = shellInstance.GetComponent<Rigidbody>();
shellRB.AddForce(15f * transform.forward, ForceMode.Impulse);
Debug.Log("velocity");
}
}
}
Hope this helps!