New to making games in Unity and I've tried to use every way possible to find the answer for this.
How would I add a touch screen function to this C# code in unity to make the player move left and right?
My code
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
private Rigidbody2D rigi;
private Animator anim;
[HideInInspector]
public bool isFacingRight = true;
public float maxSpeed = 7.0f;
public Transform groundCheck;
public LayerMask groundLayers;
private float groundCheckRadius = 0.2f;
private void Awake()
{
rigi = GetComponent<Rigidbody2D>();
anim = this.GetComponent<Animator> ();
}
void Start()
{
}
void Update()
{
}
void FixedUpdate()
{
try
{
float move = Input.GetAxis("Horizontal");
rigi.GetComponent<Rigidbody2D>().velocity = new Vector2
(move * maxSpeed, GetComponent<Rigidbody2D>().velocity.y);
this.anim.SetFloat("Speed",Mathf.Abs(move));
if((move > 0.0f && isFacingRight == false) ||
(move < 0.0f && isFacingRight == true))
{
Flip ();
}
}
catch(UnityException error)
{
Debug.LogError(error.ToString());
}
}
void Flip()
{
isFacingRight = !isFacingRight;
Vector3 playerScale = transform.localScale;
playerScale.x = playerScale.x * -1;
transform.localScale = playerScale;
}
}
You need to use the Input.touches to detect the screen touch.
Maybe in this case you should detect if the player is pressing the right/left side of the screen and moving it accordingly. You can do that by comparing the touch position, something like input.touches[0].position.x < Screen.width/2 to move right for example.
https://docs.unity3d.com/ScriptReference/Input-touches.html
Just a piece of advice, do not use GetComponent inside the update method. In this case you don't actually need it because you already have the references on the awake method.
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 using Unity to make my character jump from a moving platform where it goes up & down infinitely. The problem I'm facing is when the moving platform goes up, the jump is working perfectly but when the platform is going down, my character can't jump most often & I can see the platform is "vibrating" a bit which is weird.
Here are my codes:
Moving Platform Script [NB - Rigidbody2D is set to Kinematic]
public class Moveground : MonoBehaviour
{
[SerializeField] private Transform posTop, posBot;
private float maxTop = -0.5f;
private float maxBot = -5.0f;
[SerializeField] private float speed;
[SerializeField] private Transform startPos;
private Vector2 nextPos;
private void Start()
{
nextPos = startPos.position;
}
private void FixedUpdate()
{
if (transform.position == posTop.position)
{
nextPos = posBot.position;
}
if (transform.position == posBot.position)
{
nextPos = posTop.position;
}
transform.position = Vector2.MoveTowards(transform.position, nextPos, speed*Time.deltaTime);
}
}
PlayerController.cs (Only Jump part)
[SerializeField] private LayerMask ground;
private Collider2D coll;
private void Start()
{
coll = GetComponent<Collider2D>();
}
private void Update()
{
InputManager();
}
private void InputManager()
{
if (Input.GetButtonDown("Jump") && coll.IsTouchingLayers(ground)) // Moving Platform's layer is also "ground"
{
Jump();
}
}
private void Jump() {
rb.velocity = new Vector2(rb.velocity.x, jumpforce); // jumpforce is a float number
}
How can I resolve this issue? I'm new to Unity.
Instead of "IsTouchingLayers" try something like this in the PlayerController class:
public bool IsGrounded()
{
return Physics2D.Raycast(transform.position, Vector3.down, 0.1f, ground);
}
and play around with the distance argument, which is the 0.1f one.
If your player transform is not at the bottom of the player, you can also put in something like this instead of 0.1f:
coll.bounds.extents.y + 0.1f
I am developing a basic game on Unity to improve myself. It's a basic endless runner platform game.
If you right click when the player is on the ground, it jumps; if it's not on the ground, it falls faster.
But I couldn't figure out how to make a player die while falling when it couldn't catch the platform. Could you please check my code? I am trying to find an "if" command to make it happen.
using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PlayerControls : MonoBehaviour
{
public Rigidbody2D rb;
public Transform groundCheck;
public float groundCheckRadius;
public LayerMask whatIsGround;
private bool onGround;
float CurrentFallTime;
public float MaxFallTime = 7;
bool PlayerIsFalling;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
rb.velocity = new Vector2(5, rb.velocity.y);
onGround = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
CurrentFallTime += Time.deltaTime;
if (Input.GetMouseButtonDown(0) && onGround)
{
rb.velocity = new Vector2(rb.velocity.x, 12);
}
if (Input.GetMouseButtonDown(0) && !onGround)
{
rb.velocity = new Vector2(rb.velocity.x, -10);
}
// I want it to die and go to game over screen when it exceeds the CurrentFallTime
if ()
{
if (CurrentFallTime >= MaxFallTime)
{
SceneManager.LoadScene("GameOver");
}
}
}
}
EDIT: It solved! I simpy added "if(onGround)" and reset the CurrentFallTime. Here is the new code:
using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PlayerControls : MonoBehaviour
{
public Rigidbody2D rb;
public Transform groundCheck;
public float groundCheckRadius;
public LayerMask whatIsGround;
private bool onGround;
float CurrentFallTime;
public float MaxFallTime = 7;
bool PlayerIsFalling;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
rb.velocity = new Vector2(5, rb.velocity.y);
onGround = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
CurrentFallTime += Time.deltaTime;
if (onGround)
{
CurrentFallTime = 0f;
}
if (Input.GetMouseButtonDown(0) && onGround)
{
rb.velocity = new Vector2(rb.velocity.x, 12);
}
if (Input.GetMouseButtonDown(0) && !onGround)
{
rb.velocity = new Vector2(rb.velocity.x, -10);
}
if (CurrentFallTime >= MaxFallTime)
{
SceneManager.LoadScene("GameOver");
}
}
}
This is something that I just thought of now, so I'm not sure how well it will work, but you can create a 1-sided plane collider and position it to follow the x- and y-coordinate of the player, but stay slightly lower than the height of the ground, e.g. 1unit. Then check when the player collides with the plane, if it does then you know that the player has fallen.
So, create an empty GameObject and add the collider, no need for any mesh properties and set the collider trigger to true. Then in player controls add something like in update.
colliderGo.transform.location = new Vector3(transform.x, groundHeight - 1, transform.z)
Also in the player controller function
function onTrigger(Collider col) {
if (col.tag == "fallDetector") {
Debug.Log("What a cruel world")
playHasFallen = true;
}
}
Something like this should work.
I'm working on a simple 3D game where some balls (fixed Z position) fall along a path (using gravity and physics material) to a small flat platform and "power bounce" off this platform. The player can rotate this platform so I want to recreate a realistic bounce direction according to the platform's angle.
I'm new to coding but so far I've figured the relationship between the vector of the ball as it comes into collision with the platform and the platform's normal, which should be a perpendicular line from the surface and that can be used to reflect the ball's vector to the other direction.
I already used OnCollisionEnter and if statement to detect whether it's the platform you are colliding with, but I don't understand where to indicate the normal of the surface and how to access it. Should it be as a public class in the other object or can it be detected from the ball game object?
I tried some examples from this and other websites and got this far:
public class OnCollision : MonoBehaviour
{
public float speed = 25f;
public Rigidbody rb;
private Rigidbody rigid;
private void Start()
{
rigid = transform.GetComponent<Rigidbody>();
}
private void OnCollisionEnter(Collision collision)
{
if (collision.transform.tag == "BouncePad") {
rb.velocity = transform.up * speed;
}
}
}
Now it bounces off vertically, so I'm guessing I should change the code where the transform.up * speed part is.
Could anyone guide me, please?
Much appreciated.
If you are already using Physics material, look into the Bounciness property. A value of 0 means no bounce, a value of 1 will lead to no loss of energy. The angle of the bounce will be calculated for you. Make sure you drag the physics material onto each object-- both the ball and the wall's material will have an effect.
Finally somebody gave me a hand and came to this solution:
public class Bounce : MonoBehaviour
{
public Rigidbody rb;
public float str = 0.21f;
public float str2 = 0.15f;
// Start is called before the first frame update
private void Start()
{
rb = GetComponent<Rigidbody>();
}
private void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "BouncePad")
{
rb.AddForce(rb.velocity * str, ForceMode.Impulse);
}
if (col.gameObject.tag == "BouncePad2")
{
rb.AddForce(rb.velocity * str2, ForceMode.Impulse);
}
}
// Update is called once per frame
void Update()
{
}
}
public class BouncTest : MonoBehaviour
{
[SerializeField] private float hight = 3;
[SerializeField] private int times = 5;
[SerializeField] private float speed = 8;
private Vector3 _startPos;
private bool _checkUP;
private int _countTimes;
private float _hightbuf;
[HideInInspector]
public bool _bounceEnd;
private void Awake()
{
_startPos = transform.position;
}
public void TurnOnBounceEffect()
{
_bounceEnd = true;
_checkUP = false;
_hightbuf = hight;
_countTimes = 0;
}
private void FixedUpdate()
{
BounceEffect();
}
private void BounceEffect()
{
if (_bounceEnd)
{
if (!_checkUP)
{
if (transform.position.y <= (_startPos.y + _hightbuf))
transform.position = Vector2.MoveTowards(transform.position, new Vector2(_startPos.x, transform.position.y) + (Vector2.up * _hightbuf), speed * Time.fixedDeltaTime);
else
{
_checkUP = true;
}
}
else if (times != _countTimes)
{
if (transform.position.y > _startPos.y)
transform.position = Vector2.MoveTowards(transform.position, _startPos, speed * Time.fixedDeltaTime);
else
{
_countTimes++;
_checkUP = false;
_hightbuf /= 2;
}
}
else
{
transform.position = Vector2.MoveTowards(transform.position, _startPos, speed * Time.fixedDeltaTime);
if (transform.position.y <= _startPos.y)
{
_bounceEnd = false;
}
}
}
}
}
I created a simple script to move player on Keyboard input, though now I want to move player on touch input, how do I do this ?
Here's my code, so how do I edit this code to make it work ? I have jump working, but dunno how to do it for moving ?
using UnityEngine;
using System.Collections;
public class MoveGround : MonoBehaviour
{
public float y = 0f;
public Rigidbody2D rb;
//public float x = 0f;
//public float z = 0f;
// Use this for initialization
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
//move function
if (Input.GetKey(KeyCode.W))
{
rb.velocity = new Vector2(0, y);
}
if (!Input.GetKey(KeyCode.W))
{
rb.velocity = new Vector2(0, 0);
}
if (Input.GetKey(KeyCode.S))
{
rb.velocity = new Vector2(0, -y);
}
//move function end
}
public void Move()
{
}
}
How do you want to move your character using touch input instead of keyboard input? Your current code moves the character depending on whether the "W" or "S" keys are being pushed.
You could make two UI buttons that correspond to "forward" and "backward" keys.
Add an Event Trigger component to those buttons. Add two event types to the buttons: "Pointer Down" and "Pointer Up."
Add a function to the list of each of those events.
Put this code onto an object in your scene.
bool movingForward;
bool movingBackward;
public float speed = 0f;// set this either here in code or in the editor
public Rigidbody2D rb;
void Start (){
rb = GetComponent<Rigidbody2D>();
movingForward = false;
movingBackward = false;
}
// Your forward button will call this function
public void moveForward (){
movingForward = true;
movingBackward = false;
}
// Your backwardbutton will call this function
public void moveBackward (){
movingForward = false;
movingBackward = true;
}
//
public void stopMoving(){
movingForward = false;
movingBackward = false;
}
void Update () {
if(movingForward || movingBackward ){// we're moving
if(movingForward ){// forward
rb.velocity = new Vector2(0, speed);
}else if(movingBackward ){// backward
rb.velocity = new Vector2(0, -speed);
}
}else{// we're moving neither forward nor backward
rb.velocity = new Vector2(0, 0);// so stand still
}
}
Point each function to that object. In the Pointer Down event, choose the "moveForward" function for the button you want to move your character forward, and the "moveBackward" function for the other button.
In the Pointer Up event for both, just choose the "stopMoving" function.
It's really simplistic, but it will work.
I agree with #PolakięGames. The best way to do it is creating two UI buttons with EventTriggers attached and assigning the methods MoveForward and MoveBackwards to PointerDown and StopMoving to PointerDown. Although I would implement it differently:
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class MoveExample : MonoBehaviour {
public float Acceleration = 4f;
public float Speed = 4f;
private Vector2 _velocity = Vector2.zero;
private Rigidbody _rigidbody;
private void Start() {
_rigidbody = GetComponent<Rigidbody>();
}
// movement methods
public void Move(float velocity) { _velocity.x = velocity * Speed; }
public void MoveForward() { Move(1f); }
public void MoveBackwards() { Move(-1f); }
public void StopMoving() { Move(0f); }
private void Update() {
_rigidbody.velocity = Vector2.Lerp(_rigidbody.velocity, _velocity, Time.deltaTime * Acceleration);
}
}
That way your object will move smootly and you can control the speed and acceleration. You have to change Rigidbody to Rigidbody2D if you intend to use it with 2D Physics.