I am new to Unity and develop mobile 2d game,now I am able to make an object move right and left when I touch the screen before or after the screen center. But I want to touch the object and drag it on the x axis while my finger is still touching the screen and move,so I want the object to be in the same x position of my finger,
Any One can help me how to do it correctly:
here is the code of how I am moving the object if I touched before or after the screen center:
public class paddle : MonoBehaviour {
public Rigidbody2D rb;
public float speed;
public float maxX;
bool currentisAndroid=false;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody2D> ();
#if UNITY_ANDROID
currentisAndroid=true;
#else
currentisAndroid=false;
#endif
}
// Update is called once per frame
void Update () {
if (currentisAndroid == true) {
if (Input.GetTouch (0).position.x < Screen.width/2 && Input.GetTouch (0).phase == TouchPhase.Stationary)
moveLeft ();
else if (Input.GetTouch (0).position.x > Screen.width/2 && Input.GetTouch (0).phase == TouchPhase.Stationary)
moveRight ();
else
stop ();
} else {
float x = Input.GetAxis ("Horizontal");
//if (Input.GetTouch (0).position.x == rb.position.x && Input.GetTouch (0).phase == TouchPhase.Moved)
if (x == 0)
stop ();
if (x < 0)
moveLeft ();
if (x > 0)
moveRight ();
Vector2 pos = transform.position;
pos.x=Mathf.Clamp (pos.x,-maxX,maxX);
transform.position = pos;
}
}
void moveLeft()
{
rb.velocity = new Vector2 (-speed, 0);
}
void moveRight()
{
rb.velocity = new Vector2 (speed, 0);
}
void stop()
{
rb.velocity = new Vector2 (0, 0);
}
public float getposition()
{
return rb.position.y;
}
}
Easiest way:
Add component DragRigidbody script and you will be able to drag objects via mouse or touchScreen touches.
If I Understand correctly:
1 - Raycast from finger location vertically with your camera into the scene.
2 - select the hit object.
3 - map your camera to world coordinates and move that object according to hit point of your ray with map or game object\objects.
Physics.Raycast();
RaycastHit.collider();
Camera.main.ScreenToWorldPoint(Input.GetTouch(<0 or 1 or all>).position);
If you want to move object across a map you can track your touch and when its close to the corners move the camera on that direct (horizontal - vertical).
Related
I am making a first person shooter using bullets and I'm trying to find a way to delete the instances when it hits an enemy or the wall but its not working. The way I've done it is to give all the walls and enemy's a tag for specific collision detection but it doesn't seem to be working
for me.
plz help
using UnityEngine;
using TMPro;
public class BulletShoot : MonoBehaviour
{
//bullet
public GameObject bullet;
//bullet force
public float shootForce, upwardForce;
//Gun stats
public float timeBetweenShooting, spread, reloadTime, timeBetweenShots;
public int magazineSize, bulletsPerTap;
public bool allowButtonHold;
int bulletsLeft, bulletsShot;
//Recoil
public Rigidbody playerRb;
public float recoilForce;
//bools
bool shooting, readyToShoot, reloading;
//Reference
public Camera fpsCam;
public Transform attackPoint;
//Graphics
public GameObject muzzleFlash;
public TextMeshProUGUI ammunitionDisplay;
//bug fixing :D
public bool allowInvoke = true;
private void Awake()
{
//make sure magazine is full
bulletsLeft = magazineSize;
readyToShoot = true;
}
private void Update()
{
MyInput();
//Set ammo display, if it exists :D
//if (ammunitionDisplay != null)
//ammunitionDisplay.SetText(bulletsLeft / bulletsPerTap + " / " + magazineSize / bulletsPerTap);
}
private void MyInput()
{
//Check if allowed to hold down button and take corresponding input
if (allowButtonHold) shooting = Input.GetKey(KeyCode.Mouse0);
else shooting = Input.GetKeyDown(KeyCode.Mouse0);
//Reloading
if (Input.GetKeyDown(KeyCode.R) && bulletsLeft < magazineSize && !reloading) Reload();
//Reload automatically when trying to shoot without ammo
if (readyToShoot && shooting && !reloading && bulletsLeft <= 0) Reload();
//Shooting
if (readyToShoot && shooting && !reloading && bulletsLeft > 0)
{
//Set bullets shot to 0
bulletsShot = 0;
Shoot();
}
}
private void Shoot()
{
readyToShoot = false;
//Find the exact hit position using a raycast
Ray ray = fpsCam.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0)); //Just a ray through the middle of your current view
RaycastHit hit;
//check if ray hits something
Vector3 targetPoint;
if (Physics.Raycast(ray, out hit))
targetPoint = hit.point;
else
targetPoint = ray.GetPoint(75); //Just a point far away from the player
//Calculate direction from attackPoint to targetPoint
Vector3 directionWithoutSpread = targetPoint - attackPoint.position;
//Calculate spread
float x = Random.Range(-spread, spread);
float y = Random.Range(-spread, spread);
//Calculate new direction with spread
Vector3 directionWithSpread = directionWithoutSpread + new Vector3(x, y, 0); //Just add spread to last direction
//Instantiate bullet/projectile
GameObject currentBullet = Instantiate(bullet, attackPoint.position, Quaternion.identity); //store instantiated bullet in currentBullet
//Rotate bullet to shoot direction
currentBullet.transform.forward = directionWithSpread.normalized;
//Add forces to bullet
currentBullet.GetComponent<Rigidbody>().AddForce(directionWithSpread.normalized * shootForce, ForceMode.Impulse);
currentBullet.GetComponent<Rigidbody>().AddForce(fpsCam.transform.up * upwardForce, ForceMode.Impulse);
if(currentBullet.gameObject.CompareTag("Enemy"))
{
Destroy(currentBullet.gameObject, 3);
}
if (currentBullet.gameObject.CompareTag("Thing"))
{
Destroy(currentBullet.gameObject, 3);
}
//Instantiate muzzle flash, if you have one
if (muzzleFlash != null)
Instantiate(muzzleFlash, attackPoint.position, Quaternion.identity);
bulletsLeft--;
bulletsShot++;
//Invoke resetShot function (if not already invoked), with your timeBetweenShooting
if (allowInvoke)
{
Invoke("ResetShot", timeBetweenShooting);
allowInvoke = false;
//Add recoil to player (should only be called once)
playerRb.AddForce(-directionWithSpread.normalized * recoilForce, ForceMode.Impulse);
}
//if more than one bulletsPerTap make sure to repeat shoot function
if (bulletsShot < bulletsPerTap && bulletsLeft > 0)
Invoke("Shoot", timeBetweenShots);
}
private void ResetShot()
{
//Allow shooting and invoking again
readyToShoot = true;
allowInvoke = true;
}
private void Reload()
{
reloading = true;
Invoke("ReloadFinished", reloadTime); //Invoke ReloadFinished function with your reloadTime as delay
}
private void ReloadFinished()
{
//Fill magazine
bulletsLeft = magazineSize;
reloading = false;
}
}
I have two things to say.
The first is, it seems a little unnecessary to have a bullet object if you are using raycasting to find where you have hit, but it's alright if you want to do it like that.
The second is that the bullet object is not instant, so when you add forces to the bullet in Shoot(), the bullet still hasn't moved yet. You are then checking if it has collided with anything on the same frame, also in Shoot(), which still means the bullet hasn't moved yet. I would recommend moving the collision detection out of the Shoot() method and into a separate method that I would then call in update(), separately from Input().
Hope this helped :D
I`m trying to make a wallrun in unity like the wallrun of the Prince of Persia.
The idea is that when you are touching the wall and you press "left shift" the player would run some seconds without falling.
I would like to add that if you press "enter" the character would jump to the side using the Wall as support for impulse.
You can watch this in the first minutes of the video:
https://www.youtube.com/watch?v=zsnB7HEiLr0
I have made this script for the character controller:
public Transform playerPosition;
//controls the x movement. (right/left)
public float horizontalmove;
//controls the y movement. (forward/back)
public float verticalmove;
//controls the movement direction.
private Vector3 playerInput;
//Here I store my character controller.
public CharacterController player;
//controls the player speed.
public float playerSpeed;
//controls de movement direction according to camera
public Vector3 movePlayer;
//controls the last movement
public Vector3 lastMovePlayer;
public float gravity = 9.8f;
public float fallVelocity;
public float jumpForce = 5.0f;
public float verticalSpeed;
private RaycastHit HitR;
private RaycastHit HitL;
//Here I store the main camera
public Camera mainCamera;
//It stores the camera direction when the player is looking forward.
private Vector3 camForward;
//It stores the camera direction when the player is looking right.
private Vector3 camRight;
//Checks
//The meaning of Caida is fall.
public bool Caida;
//The meaning of salto is jump.
public bool Salto;
public bool Wallrun;
public bool WallrunCount;
// Start is called befoe the first frame update
void Start()
{
//i store the character controler.
player = GetComponent<CharacterController>();
Caida = true;
}
// Update is called once per frame
void Update()
{
if (Wallrun == true)
{
Caida = false;
}
if (Salto == true)
{
fallVelocity -= gravity * Time.deltaTime;
movePlayer = lastMovePlayer;
}
if (Caida == true)
{
fallVelocity -= gravity * Time.deltaTime;
}
if (player.isGrounded && Wallrun == false)
{
Caida = false;
Salto = false;
WallrunCount = false;
//I assign the horizontal move to the w and s keys.
horizontalmove = Input.GetAxis("Horizontal");
//I assign the vertical move to the a and d keys.)
verticalmove = Input.GetAxis("Vertical");
//controls the movement direction
playerInput = new Vector3(horizontalmove, 0, verticalmove);
//limits the player speed. With this method if teh player waalks in diagonal doesn´t
//exceed the speed limit.
playerInput = Vector3.ClampMagnitude(playerInput, 1);
// It calls the function that give the camera look direction.
camDirection();
//Here, It`s calculates the player movement considering the camera point and the movement
//we have assing to teh player earlier
//With this method the player always moves looking to the camera
movePlayer = playerInput.x * camRight + playerInput.z * camForward;
//The movement * the speed we want.
movePlayer = movePlayer * playerSpeed;
//we are going to say to the player where is looking at.
player.transform.LookAt(player.transform.position + movePlayer);
//It gives the gravity to the player.
fallVelocity = -gravity * Time.deltaTime;
if (Input.GetKeyDown(KeyCode.Space))
{
Salto = true;
fallVelocity = jumpForce;
}
}
else if (!player.isGrounded && Salto == false && Wallrun == false)
{
Caida = true;
}
movePlayer.y = fallVelocity;
//we give the movement to th eplayer.
player.Move(movePlayer * Time.deltaTime);
lastMovePlayer = movePlayer;
}
private void OnTriggerStay(Collider other)
{
if (Input.GetKeyDown(KeyCode.LeftShift) && Wallrun == false && WallrunCount == false)
{
if (Input.GetKey("w"))
{
Wallrun = true;
WallrunCount = true;
fallVelocity = 5f;
movePlayer.y = fallVelocity;
movePlayer.z = movePlayer.z * 1.6f;
if (Physics.Raycast(transform.position, transform.right, out HitR, 1))
{
movePlayer.x = 1.6f;
}
else if (Physics.Raycast(transform.position, -transform.right, out HitL, 1))
{
movePlayer.x = -1.6f;
}
StartCoroutine(wallrunTime());
}
}
}
void camDirection()
{
//we store the forward and right directions here.
camForward = mainCamera.transform.forward;
camRight = mainCamera.transform.right;
//we block the direction and the camera direction because we are not going to use it.
camForward.y = 0;
camRight.y = 0;
//It gives as the normalized vectors.
camForward = camForward.normalized;
camRight = camRight.normalized;
}
private void OnControllerColliderHit(ControllerColliderHit hit)
{
if (!player.isGrounded && hit.normal.y < 0.1f)
{
if (Input.GetKeyDown(KeyCode.Space))
{
fallVelocity = jumpForce;
movePlayer = hit.normal * 7;
player.transform.LookAt(player.transform.position + movePlayer);
}
}
}
IEnumerator wallrunTime()
{
yield return new WaitForSeconds(1);
Wallrun = false;
}
As you can see, when the player enters the leftshift it checks to what direction is moving the character, if this is front (w) the script make the z movement * 1.6 (to make the character run a bit in the wall) and the character go a bit up bit the y axis.Then, the script checks if the Wall it i son the right or on the left and, depending on where the wall is, sticks the character to that wall.
private void OnTriggerStay(Collider other)
{
if (Input.GetKeyDown(KeyCode.LeftShift) && Wallrun == false && WallrunCount == false)
{
if (Input.GetKey("w"))
{
Wallrun = true;
WallrunCount = true;
fallVelocity = 5f;
movePlayer.y = fallVelocity;
movePlayer.z = movePlayer.z * 1.6f;
if (Physics.Raycast(transform.position, transform.right, out HitR, 1))
{
movePlayer.x = 1.6f;
}
else if (Physics.Raycast(transform.position, -transform.right, out HitL, 1))
{
movePlayer.x = -1.6f;
}
StartCoroutine(wallrunTime());
}
}
}
With this method, I can make the character jump when the player enters space because the character is hitting the wall (a condition required to bounce in the wall).
And after some seconds, the character falls simulating a wallrun.
IEnumerator wallrunTime()
{
yield return new WaitForSeconds(1);
Wallrun = false;
}
The problem is that this works perfectly if the character makes the wallrun when is looking in the same direction as the axes of the environment.
When the character z axis is looking at the same direction of the environment z axes it works perfectly. But when the axes are not looking at the same direction is a disaster. I show you a video I have recorded.
https://youtu.be/KH7rE9kh5d0
The problem, I suppose, is that with the code I have written, I'm moving the character according to the axes of the environment, and not its axes, so I have to tell him to move according to his own.
My teacher says I might have to change the way I make the character move. I would like to know if you can tell me a way to fix this without changing the movement method or if it is not possible, how can I change that movement.
Thank you in advance.
I am confused as to why my game cursor follow script does not seem to perform differently based on the character's position. I want the player to press "E" if the player hovers the mouse over the character's hand and clicks and drags the arm will move up and down following the mouse position.
The script was working until I moved my character along the X axis and found that the location the mouse had to click and drag stayed at the arm's original position even as the
character, his arm, and camera moved away. Would anyone have any idea why? I've pasted in the script for finding the Mouse's position and the script for having my game object copy the mouse's position.
I uploaded some videos of the script working on YouTube as well
https://www.youtube.com/watch?v=grhnqckOfc0
https://www.youtube.com/watch?v=ZlLLgnU8yMc
Thanks for your time!
public static class GameCursor
{
public static LayerMask mask;
public static Vector2 WorldPosition
{
get
{
float distance;
int mask = 1<<9; //setting layer mask to layer 9
mask = ~mask; //setting the layer mask to ignore layer(~)
//adding in the layermask to raycast will ignore 9th layer
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin, ray.direction * 10000f, Color.black);
if (_gamePlane.Raycast(ray, out distance))
return ray.GetPoint(distance);
return Vector2.zero;
}
}
private static Plane _gamePlane = new Plane(Vector3.forward,0);
}
public GameObject ArmR;
public static Vector2 OffsetPoint;
public Vector2 OffsetVec2;
void Start ()
{
}
private void Update()
{
if (Input.GetKey (KeyCode.E)) {
Follow ();
}
if (Input.GetKeyUp (KeyCode.E)) {
}
//print (transform.eulerAngles.z);
//Offset.transform.position = OffsetVec2;
OffsetPoint = GameCursor.WorldPosition + OffsetVec2;
Vector3 clampedRotation = transform.eulerAngles;
// Clamp the z value
if (clampedRotation.z > 90.0f) clampedRotation.z = 180.0f - clampedRotation.z;{
clampedRotation.z = Mathf.Clamp (clampedRotation.z, 0, 90);
clampedRotation.z = Mathf.Clamp (clampedRotation.z, -90, 180);
}
// assign the clamped rotation
ArmR.transform.rotation = Quaternion.Euler(clampedRotation);
//if(ArmR.transform.eulerAngles.z >= 350 || transform.eulerAngles.z <= 270){
//Debug.Log ("no");
//}
if(ArmR.transform.eulerAngles.z == 0){
//Debug.Log ("AT0");
}
if(ArmR.transform.eulerAngles.z == 90){
//Debug.Log ("AT90");
}
}
void Follow(){
ArmR.transform.up = -GameCursor.WorldPosition + OffsetVec2;
}
private void OnDrawGizmos()
{
Gizmos.DrawIcon(GameCursor.WorldPosition, "wallll", true);
}
}
Hello and thanks for reading this post.
I have 2 objects: A player Object and a JumpButton Object.
The Player object is the player. ofc. The JumpButton Object is an object that I want to make the player jump when you use a touch screen device aka android phone.
This is my Script that is assinged to my JumpButton: using UnityEngine; using System.Collections;
using UnityEngine;
using System.Collections;
public class JumpButtonScript : MonoBehaviour {
public GameObject player;
public GameObject JumpButton;
// Use this for initialization
void Start () {
player = GameObject.Find ("player");
}
// Update is called once per frame
void Update () {
if ((Input.touchCount == 1) && (Input.GetTouch(0).phase == TouchPhase.Began))
{
}
}
}
This is the script that allows me to control the player with arrow keys.
using UnityEngine;
using System.Collections;
public class RobotController : MonoBehaviour {
//This will be our maximum speed as we will always be multiplying by 1
public float maxSpeed = 2f;
public GameObject player;
public GameObject sprite;
//a boolean value to represent whether we are facing left or not
bool facingLeft = true;
//a value to represent our Animator
Animator anim;
//to check ground and to have a jumpforce we can change in the editor
bool grounded = true;
public Transform groundCheck;
public float groundRadius = 1f;
public LayerMask whatIsGround;
public float jumpForce = 300f;
private bool isOnGround = false;
void OnCollisionEnter2D(Collision2D collision) {
isOnGround = true;
}
void OnCollisionExit2D(Collision2D collision) {
anim.SetBool ("Ground", grounded);
anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);
isOnGround = false;
}
// Use this for initialization
void Start () {
player = GameObject.Find("player");
//set anim to our animator
anim = GetComponent <Animator>();
}
void FixedUpdate () {
//set our vSpeed
//set our grounded bool
grounded = Physics2D.OverlapCircle (groundCheck.position, groundRadius, whatIsGround);
//set ground in our Animator to match grounded
anim.SetBool ("Ground", grounded);
float move = Input.GetAxis ("Horizontal");//Gives us of one if we are moving via the arrow keys
//move our Players rigidbody
rigidbody2D.velocity = new Vector3 (move * maxSpeed, rigidbody2D.velocity.y);
//set our speed
anim.SetFloat ("Speed",Mathf.Abs (move));
//if we are moving left but not facing left flip, and vice versa
if (move > 0 && !facingLeft) {
Flip ();
} else if (move < 0 && facingLeft) {
Flip ();
}
}
void Update(){
if ((isOnGround == true && Input.GetKeyDown (KeyCode.UpArrow)) || (isOnGround == true && Input.GetKeyDown (KeyCode.Space))) {
anim.SetBool("Ground",false);
rigidbody2D.AddForce (new Vector2 (0, jumpForce));
}
if (isOnGround == true && Input.GetKeyDown (KeyCode.DownArrow))
{
gameObject.transform.localScale = new Vector3(transform.localScale.x, 0.2f, 0.2f);
}
if (isOnGround == true && Input.GetKeyUp (KeyCode.DownArrow))
{
gameObject.transform.localScale = new Vector3(transform.localScale.x, 0.3f, 0.3f);
}
}
//flip if needed
void Flip(){
facingLeft = !facingLeft;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
As you can see, then I managed to make the player move on arrow keys, but how can I make it jump when I hit the jump button (touch Screen press), as on an Android Phone?
I really hope you can help me.
If your problem is how to handle input, try this code we will make ray from camera to mousepos in screen and check tag to see what we hitted
public class handleInput: MonoBehaviour {
void Update () {
if (Input.GetMouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit)) {
if (hit.collider.tag=="jumpbutton"){
jump();
}
}
}
}
}
and for the jumping part you can do this , adding a force to player to send him up and gravity should pull him down
if (grounded == true)
{
rigidbody.AddForce(Vector3.up* jumpSpeed);
grounded = false;
}
I'm wanting my player to move to the left when the player hits the left of the screen. Right now, my player only moves as and when I hold down my mouse button. What I'm really wanting is for him to continually move to the left until he hits the target position when I press the screen once.
Can someone please tell me what I'm missing from my code to allow this to happen?
void FixedUpdate()
{
if(Input.GetMouseButtonDown(0))
{
if(Input.mousePosition.x < (Screen.width*2)/3 && Input.mousePosition.y > Screen.height/3)
{
if(position == middle)
{
MoveLeft();
}
}
}
}
void MoveLeft()
{
var pos = rigidbody.position;
float xPosition = left.transform.position.x;
pos.x = Mathf.Lerp(pos.x, xPosition, speed * Time.deltaTime);
rigidbody.position = pos;
}
My method is in the FixedUpdate because I'm moving the players rigidbody as oppose to translating the actual player.
Right now the player only moves when you hit mouse button because that's how your code is written: you check if the mouse is pressed every frame, and only if it is move the rigidbody.
If you want the player to move regardless of whether the mouse is still pressed or not, you should create some kind of variable to save the state of the player, and set to move left when the mouse button is pressed and set it to stop when the player reaches his target.
If I correctly understood your goal, it would look something like this:
bool moveLeft = false;
void FixedUpdate()
{
if(Input.GetMouseButtonDown(0)
&& (Input.mousePosition.x < (Screen.width*2)/3 && Input.mousePosition.y > Screen.height/3))
{
moveLeft = true;
}
if (moveLeft
&& (position == middle))
{
MoveLeft();
}
else
{
moveLeft = false;
}
}
void MoveLeft()
{
var pos = rigidbody.position;
float xPosition = left.transform.position.x;
pos.x = Mathf.Lerp(pos.x, xPosition, speed * Time.deltaTime);
rigidbody.position = pos;
}