I'm using my android device to detect the touched position and move my object, but my object change the position way to far it disapears from my camera view, do I need to use ScreenToWorldPoint? It so, how do I use it?
Here is my code:
void Update() {
for (var i = 0; i < Input.touchCount; i++) {
if (Input.GetTouch(i).phase == TouchPhase.Began) {
transform.position = new Vector3 (Input.GetTouch(i).position.x, Input.GetTouch(i).position.y, transform.position.z);
}
}
}
You can try like this:
private void Update()
{
for (var i = 0; i < Input.touchCount; i++)
{
if (Input.GetTouch(i).phase == TouchPhase.Began)
{
var worldPosition = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position);
transform.position = worldPosition;
}
}
}
You can try this,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SelectObject : MonoBehaviour {
// Use this for initialization
GameObject hitObj;
RaycastHit hit;
private float speed = 1;
void Start () {
}
// Update is called once per frame
void Update () {
foreach (Touch touch in Input.touches) {
switch (touch.phase) {
case TouchPhase.Began:
Ray ray = Camera.main.ScreenPointToRay (touch.position);
if (Physics.Raycast (ray, out hit, 10)) {
hitObj = hit.collider.gameObject;
}
break;
case TouchPhase.Moved:
// If the finger is on the screen, move the object smoothly to the touch position
float step = speed * Time.deltaTime; // calculate distance to move
if(hitObj != null)
hitObj.transform.position = Camera.main.ScreenToWorldPoint(new Vector3 (touch.position.x, touch.position.y, hitObj.transform.position.z));
break;
}
}
}
}
Related
I have the following issue in my game:
There're two characters in the scene and they can shoot at each other. There is an empty game object attached in the front of each other called "SpawnBullet", which spawns the projectile, as you can see in the image.
The problem is that the game object called "Player 2" is shooting at himself, the bullet is going in his direction. Even when I rotate the SpawnBullet. In Player 1 it works fine.
This script is attached to the players
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Moviment : MonoBehaviour
{
//player variables
public GameObject player;
public GameObject[] Personagens;
//moving variables
Vector3 targetPosition;
float posY = 1;
public float velocity = 0.2f;
public float movMax = 3;
public bool ismoving = false;
public bool moveEnabled;
public int aux;
//bullet variables
public GameObject projetil;
private GameObject SpawBala;
public float ProjetilVeloc = 500f;
private void Start()
{
//sets the first unit as the active unit at the start of the game
Personagens[0].GetComponent<Jogador>().isPlayer = true;
TurnStart();
}
// Update is called once per frame
void Update()
{
//left mouse button to start movement
if (Input.GetMouseButtonDown(0))
{
//raycast checks and returns an object, if it's a tile, the unit moves
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
ismoving = true;
if (Physics.Raycast(ray, out hit))
{
if (hit.transform.tag == "Tile")
{
//checks if the tile is available based on the max movement of the unit
Tile tileAux = hit.transform.gameObject.GetComponent<Tile>();
Jogador scriptJog = player.GetComponent<Jogador>();
if ((tileAux.TilePostion.x - scriptJog.GridPosition.x) + (tileAux.TilePostion.y - scriptJog.GridPosition.y) >= -movMax && (tileAux.TilePostion.x - scriptJog.GridPosition.x) + (tileAux.TilePostion.y - scriptJog.GridPosition.y) <= movMax)
{
if ((tileAux.TilePostion.x - scriptJog.GridPosition.x) - (tileAux.TilePostion.y - scriptJog.GridPosition.y) >= -movMax && (tileAux.TilePostion.x - scriptJog.GridPosition.x) - (tileAux.TilePostion.y - scriptJog.GridPosition.y) <= movMax)
{
targetPosition = (hit.transform.position);
targetPosition.y = posY;
moveEnabled = true;
}
}
}
}
}
//right click to shoot
if (Input.GetMouseButtonDown(1))
{
//raycast checks and returns an object, if it's a tile, the unit shoots
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
//checks if the tile is available based on the line and column of the unit
Tile tileAux = hit.transform.gameObject.GetComponent<Tile>();
Jogador scriptJog = player.GetComponent<Jogador>();
if (tileAux.TilePostion.x == scriptJog.GridPosition.x || tileAux.TilePostion.y == scriptJog.GridPosition.y)
{
if (tileAux.TilePostion.x > scriptJog.GridPosition.x)
tileAux.TilePostion.x = 5;
else
tileAux.TilePostion.x = 0;
if (tileAux.TilePostion.y > scriptJog.GridPosition.y)
tileAux.TilePostion.y = 5;
else
tileAux.TilePostion.y = 0;
Debug.Log(tileAux.TilePostion.x);
Debug.Log(tileAux.TilePostion.y);
//instantiates the bullet
GameObject tiro = Instantiate(projetil, SpawBala.transform.position, Quaternion.identity, player.transform);
Rigidbody BalaRigid = tiro.GetComponent<Rigidbody>();
BalaRigid.AddForce(Vector3.forward * ProjetilVeloc);
}
}
}
//player moves until reaches the position
if (player.transform.position != targetPosition)
{
player.transform.position = Vector3.MoveTowards(player.transform.position, targetPosition, velocity);
if (player.transform.position == targetPosition)
ismoving = false;
}
//if player reaches position, it's deselected
if (moveEnabled && !ismoving)
{
player.GetComponent<Jogador>().isPlayer = false;
moveEnabled = false;
}
}
public void TurnStart()
{
//makes the selected unit the active unit
for (int i = 0; i < Personagens.Length; i++)
{
if (Personagens[i].GetComponent<Jogador>().isPlayer == true)
{
player = Personagens[i];
posY = player.transform.position.y;
targetPosition = player.transform.position;
SpawBala = player.transform.GetChild(0).gameObject;
}
}
}
public void TurnEnd()
{
//desactivates all units
for(int i = 0; i < Personagens.Length; i++)
{
Personagens[i].GetComponent<Jogador>().isPlayer = false;
}
}
}
And I'm using this section (copied from above) to shoot:
//right click to shoot
if (Input.GetMouseButtonDown(1))
{
//raycast checks and returns an object, if it's a tile, the unit shoots
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
//checks if the tile is available based on the line and column of the unit
Tile tileAux = hit.transform.gameObject.GetComponent<Tile>();
Jogador scriptJog = player.GetComponent<Jogador>();
if (tileAux.TilePostion.x == scriptJog.GridPosition.x || tileAux.TilePostion.y == scriptJog.GridPosition.y)
{
if (tileAux.TilePostion.x > scriptJog.GridPosition.x)
tileAux.TilePostion.x = 5;
else
tileAux.TilePostion.x = 0;
if (tileAux.TilePostion.y > scriptJog.GridPosition.y)
tileAux.TilePostion.y = 5;
else
tileAux.TilePostion.y = 0;
Debug.Log(tileAux.TilePostion.x);
Debug.Log(tileAux.TilePostion.y);
//instantiates the bullet
GameObject tiro = Instantiate(projetil, SpawBala.transform.position, Quaternion.identity, player.transform);
Rigidbody BalaRigid = tiro.GetComponent<Rigidbody>();
BalaRigid.AddForce(Vector3.forward * ProjetilVeloc);
}
}
}
When you add the force to the bullet you are using Vector3.forward. You need to use transform.forward instead.
Vector3.forward is always a constant (0, 0, 1). Think of the it as the forward direction of your world. It never changes.
transform.forward however will give the forward facing direction of the gameObject (the player). When you rotate your player it's transform.forward will change accordingly.
The reason Player 1 appears to be working correctly is because it is facing the same direction as Vector3.forward.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OnMouseOverEvent : MonoBehaviour
{
public GameObject[] objects;
private Vector3[] originalpos;
private void Start()
{
originalpos = new Vector3[objects.Length];
for (int i = 0; i < objects.Length; i++)
{
originalpos[i] = objects[i].transform.position;
}
}
private void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100))
{
if (hit.transform.tag == "Test")
{
// if (transform.position.z != originalpos.z - 3)
// StartCoroutine(moveToX(transform, new Vector3(transform.position.x, transform.position.y, transform.position.z - 3), 0.1f));
}
else
{
// StartCoroutine(moveToX(transform, originalpos, 0.1f));
}
}
else
{
// reset
// StartCoroutine(moveToX(transform, originalpos, 0.1f));
}
}
bool isMoving = false;
IEnumerator moveToX(Transform fromPosition, Vector3 toPosition, float duration)
{
//Make sure there is only one instance of this function running
if (isMoving)
{
yield break; ///exit if this is still running
}
isMoving = true;
float counter = 0;
//Get the current position of the object to be moved
Vector3 startPos = fromPosition.position;
while (counter < duration)
{
counter += Time.deltaTime;
fromPosition.position = Vector3.Lerp(startPos, toPosition, counter / duration);
yield return null;
}
isMoving = false;
}
}
The script was working fine when objects and originalpos were singles.
But now I made them arrays since I have more then one gameobject.
I have 3 gameobjects tagged : "Test" , "Test1" , "Test2"
I want to perform them same action but for each object hit.
If hitting "Test" move only "Test" on z - 3 and then back to it's original pos.
If hitting "Test1" move only "Test1" on z - 3 and then back to it's original pos. And same for "Test2".
Make the same action but only for the hitting object.
You can use Physics.RaycastAll, it returns RaycastHit[] which you can loop through.
Like so:
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit[] hits = Physics.RaycastAll(ray, 100f);
// For each object that the raycast hits.
foreach (RaycastHit hit in hits) {
if (hit.collider.CompareTag("Test")) {
// Do something.
} else if (hit.collider.CompareTag("Test1")) {
// Do something.
} else if (hit.collider.CompareTag("Test2")) {
// Do something.
}
}
I follow this tutorial
https://www.youtube.com/watch?v=SrCUO46jcxk
for multitouch, it work. And trying to add drag functionality on each object simultaneously with multiple finger.
This is my code for button i add some code to make it draggable each object simultaneously but it work on only single object. I tried all relevant post and tutorial but not able perform, please help??
using System.Collections;
using UnityEngine;
public class Button : MonoBehaviour{
public Color defaultColour;
public Color selectedColour;
private Material mat;
private Vector3 screenPoint;
private Vector3 offset;
void Start(){
mat = GetComponent<Renderer> ().material;
}
void OnTouchDown(){
mat.color = selectedColour;
Debug.Log ("Touch Down");
screenPoint = Camera.main.WorldToScreenPoint (transform.position);
offset = transform.position - Camera.main.ScreenToWorldPoint (new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
}
void OnTouchUp(){
mat.color = defaultColour;
Debug.Log ("Touch Up");
}
void OnTouchStay(){
mat.color = selectedColour;
Debug.Log ("Touch Stay");
Vector3 curScreenPoint = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
Vector3 curPosition = Camera.main.ScreenToWorldPoint (curScreenPoint) + offset;
transform.position = curPosition;
}
void OnTouchExit(){
mat.color = defaultColour;
Debug.Log ("Touch Exit");
}
}
This code is for Input Touch functionality
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TouchInput : MonoBehaviour {
public LayerMask touchInputMask;
private static List<GameObject> touchList = new List<GameObject>();
private GameObject[] touchesOld;
private RaycastHit hit;
void Update () {
#if UNITY_EDITOR
if(Input.GetMouseButton(0) || Input.GetMouseButtonDown(0) || Input.GetMouseButtonUp(0)){
touchesOld = new GameObject[touchList.Count];
touchList.CopyTo(touchesOld);
touchList.Clear();
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out hit, touchInputMask)){
GameObject recipient = hit.transform.gameObject;
touchList.Add(recipient);
if (Input.GetMouseButtonDown(0)){
recipient.SendMessage("OnTouchDown",hit.point,SendMessageOptions.DontRequireReceiver);
}
if (Input.GetMouseButtonUp(0)){
recipient.SendMessage("OnTouchUp",hit.point,SendMessageOptions.DontRequireReceiver);
}
if (Input.GetMouseButton(0)){
recipient.SendMessage("OnTouchStay",hit.point,SendMessageOptions.DontRequireReceiver);
}
}
foreach (GameObject g in touchesOld){
if (!touchList.Contains(g)){
g.SendMessage("OnTouchExit",hit.point,SendMessageOptions.DontRequireReceiver);
}
}
}
#endif
if (Input.touchCount > 0){
touchesOld = new GameObject[touchList.Count];
touchList.CopyTo(touchesOld);
touchList.Clear();
foreach (Touch touch in Input.touches){
Ray ray = Camera.main.ScreenPointToRay (touch.position);
//RaycastHit hit;
if (Physics.Raycast(ray, out hit, touchInputMask)){
GameObject recipient = hit.transform.gameObject;
touchList.Add(recipient);
if (touch.phase == TouchPhase.Began){
recipient.SendMessage("OnTouchDown",hit.point,SendMessageOptions.DontRequireReceiver);
}
if (touch.phase == TouchPhase.Ended){
recipient.SendMessage("OnTouchUp",hit.point,SendMessageOptions.DontRequireReceiver);
}
if (touch.phase == TouchPhase.Stationary || touch.phase == TouchPhase.Moved){
recipient.SendMessage("OnTouchStay",hit.point,SendMessageOptions.DontRequireReceiver);
}
if (touch.phase == TouchPhase.Canceled){
recipient.SendMessage("OnTouchExit",hit.point,SendMessageOptions.DontRequireReceiver);
}
}
}
foreach (GameObject g in touchesOld){
if (!touchList.Contains(g)){
g.SendMessage("OnTouchExit",hit.point,SendMessageOptions.DontRequireReceiver);
}
}
}
}
}
Now finally perform this process, i could perform this process in two ways
Using touchScript library, it has a rich feature we can drag, rotate, translate and scale multiple object in one time.
https://www.youtube.com/watch?v=HHLBJ1Ss2S0
Note: this is older video, now it changes but it is almost same.
[TouchScript is available in asset store for free]
other option, attach below code in empty gameobject or in camera(add tag layer)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public struct objectst {
public Vector3 screenPoint;
public Vector3 offset;
}
public class TouchInput : MonoBehaviour {
public LayerMask touchInputMask;
private static List<GameObject> touchList = new List<GameObject>();
public static Dictionary<int,objectst> touchobjects = new Dictionary<int,objectst>();
private GameObject[] touchesOld;
private RaycastHit hit;
public Text Count, IndexLift;
private Vector3 targetPos;
void Update () {
int nbTouches = Input.touchCount;
if(nbTouches > 0)
{
nbTouches = 5;
print(nbTouches + " touch(es) detected");
touchesOld = new GameObject[touchList.Count];
touchList.CopyTo(touchesOld);
touchList.Clear();
for (int i = 0; i < nbTouches ; i++)
{
Touch touch = Input.GetTouch(i);
print("Touch index " + touch.fingerId + " detected at position " + touch.position);
Ray ray = Camera.main.ScreenPointToRay (touch.position);
if (Physics.Raycast(ray, out hit, touchInputMask)){
GameObject recipient = hit.transform.gameObject;
touchList.Add(recipient);
//recipient.;
if (touch.phase == TouchPhase.Began){
objectst tempobj = new objectst ();
tempobj.screenPoint = Camera.main.WorldToScreenPoint (recipient.transform.position);
tempobj.offset = recipient.transform.position - Camera.main.ScreenToWorldPoint (new Vector3 (touch.position.x, touch.position.y, tempobj.screenPoint.z));
touchobjects.Add(touch.fingerId,tempobj);
}
if (touch.phase == TouchPhase.Stationary || touch.phase == TouchPhase.Moved){
Vector3 curScreenPoint = new Vector3 (touch.position.x, touch.position.y,
touchobjects[touch.fingerId].screenPoint.z);
Vector3 curPosition = Camera.main.ScreenToWorldPoint (curScreenPoint) + touchobjects[touch.fingerId].offset;
recipient.transform.position = curPosition;
}
if (touch.phase == TouchPhase.Ended){
Vector3 curScreenPoint = new Vector3 (touch.position.x, touch.position.y,
touchobjects[touch.fingerId].screenPoint.z);
Vector3 curPosition = Camera.main.ScreenToWorldPoint (curScreenPoint) - touchobjects[touch.fingerId].offset;
recipient.transform.position = curPosition;
}
if (touch.phase == TouchPhase.Canceled){
}
}
}
foreach (GameObject g in touchesOld){
if (!touchList.Contains(g)){
g.SendMessage("OnTouchExit",hit.point,SendMessageOptions.DontRequireReceiver);
}
}
}
}
}
I have a script to move my character(player)
The script should be fine and it does not have any errors, although when I press play I try to use the arrows and it does not work and I don't know why.
Here is the code. I appreciate any help you can give me, thanks
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
Direction currentDir;
Vector2 input;
bool isMoving = false;
Vector3 startPos;
Vector3 endPos;
float t;
public float walkSpeed = 3f;
// Update is called once per frame
void Update()
{
if (isMoving)
{
input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
if (Mathf.Abs(input.x) > input.y)
input.y = 0;
else
input.x = 0;
if (input != Vector2.zero)
{
StartCoroutine(Move(transform));
}
}
}
public IEnumerator Move(Transform entity)
{
isMoving = true;
startPos = entity.position;
t = 0;
endPos = new Vector3(startPos.x + System.Math.Sign(input.x), startPos.y +
System.Math.Sign(input.y), startPos.z);
while (t < 1f)
{
t += Time.deltaTime * walkSpeed;
entity.position = Vector3.Lerp(startPos, endPos, t);
yield return null;
}
isMoving = false;
yield return 0;
}
enum Direction
{
North,
East,
South,
West
}
}
Change
void Update()
{
if (isMoving)
{
to
void Update()
{
if (!isMoving)
{
Otherwise, on each Update you check your isMoving variable and do nothing if it is false. The only place where isMoving could become true is your Move coroutine, but it could only be launched from Update, which does not do anything since isMoving is false.
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;
}