Move Object Using Raycast - c#

I am trying to move the y position of a UI element in it's local space by clicking and dragging with the SteamVR controller and a raycast. I am getting what appear to me to be unpredictable results.
I am trying to get the position of the raycast at the start of the drag and move it the distance between where it is and where it was started while dragging.
Here is my code:
if (hit.transform.name == "Content" && scrollSet == false)
{
content = hit.transform;
scrollSet = true;
scrollPos = hit.transform.position ;
}
if (scrollSet == true)
{
if (rController.triggerPressed)
{
y = hit.transform.position.y - scrollPos.y;
content.transform.localPosition = new Vector3(content.transform.localPosition.x, content.localPosition.y + y, content.transform.localPosition.z);
}
else
{
scrollSet = false;
}
}

you can convert the .MovePosition to .MoveTowards. But it still jumped around. It turns out that the code was only executing during the frame in which you right-clicked, so move it out of the if statement.
Here's the entire script placed into the main camera. You always need to have a target selected, so to prevent errors you need to put a gameObject with a rigidbody into "bTarg".
public class ClickTarget : MonoBehaviour {
private GameObject target; private Vector3 destination; private float distance; private Vector3 tTrans;
public GUIText targetDisplay; public float speed; public GameObject bTarg;
void Start () { targetDisplay.text = ""; distance = 0.0f; target = bTarg; }
void Update () { if(Input.GetButtonDown("Fire1")){ Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if(Physics.Raycast(ray, out hit)){ if(hit.collider != null){ if(hit.collider.tag == "Unit"){ target = hit.collider.gameObject; targetDisplay.text = "Unit: " + hit.collider.gameObject.name; destination = target.transform.position; target.rigidbody.freezeRotation = false; } if(hit.collider.tag == "Building"){ target = hit.collider.gameObject; targetDisplay.text = "Building: " + hit.collider.gameObject.name; } } } } }
void FixedUpdate(){ if (Input.GetButtonDown ("Fire2") && target.tag == "Unit" && GUIUtility.hotControl == 0) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if(Physics.Raycast(ray,out hit)){ destination = hit.point; } }
tTrans = target.transform.position;
distance = Vector3.Distance (tTrans, destination);
if(target.tag == "Unit"){
if (distance > .2f) {
target.transform.LookAt (destination);
target.transform.position = Vector3.MoveTowards (target.transform.position, destination, speed);
target.rigidbody.freezeRotation = true;
}
}
} }

Related

very basic 2.5d rope physics

So I want to make a 2.5d grappling rope that lets the player swing around objects for quicker turning, but the code that I wrote doesn't work. The player just stops all velocity after a short amount of time.
public Transform player;
private float tikTok;
public LayerMask layerMask;
Vector3 tetherPoint;
Transform tetherObject;
Vector3 currentTether;
float tetherLength;
bool isTethered;
Vector3 previousPlayerPosition;
if (Input.GetKey(KeyCode.Space) && Time.time >= tikTok && !isTethered) {
// this part works fine and dandy
Ray ray = new Ray(player.position, player.forward);
if (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, layerMask)) {
tetherPoint = hit.point;
tetherObject = hit.transform;
currentTether = tetherObject.position;
tetherLength = Vector3.Distance(player.position, tetherPoint);
isTethered = true;
}
} else if (isTethered && Input.GetKey(KeyCode.Space)) {
// this part does not
if (Vector3.Distance(player.position, tetherPoint) > tetherLength) {
player.position -= (Vector3.Distance(player.position, tetherPoint) - tetherLength) * (player.position - tetherPoint).normalized;
print((player.position - previousPlayerPosition).normalized);
player.gameObject.GetComponent<Rigidbody>().velocity = player.gameObject.GetComponent<Rigidbody>().velocity.magnitude * (player.position - previousPlayerPosition).normalized;
}
} else if (isTethered && !Input.GetKey(KeyCode.Space)) {
isTethered = false;
tetherPoint = Vector3.zero;
tetherObject = null;
currentTether = Vector3.zero;
tetherLength = 0;
}
if (tetherObject != null) {
if (currentTether != tetherObject.position) {
tetherPoint += currentTether - tetherObject.position;
currentTether = tetherObject.position;
}
}
previousPlayerPosition = player.position;```

why gameobject / raycast when dragged is not accurately following the touch position in unity

so I made a script for multitouch using raycast. when dragged faster, the gameobject will be released, but when moving the gameobject slowly it follows the touch. here the codes
Vector2[] startPos = new Vector2[5];
Touch[] touch = new Touch[5];// Update is called once per frame
void FixedUpdate()
{
Debug.Log(Input.touchCount);
if (Input.touchCount > 0)
{
touch[Input.touchCount-1] = Input.GetTouch(Input.touchCount-1);
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(touch[Input.touchCount-1].position);
RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero, Mathf.Infinity);
if (hit.transform != null)
{
if (touch[Input.touchCount - 1].phase == TouchPhase.Moved)
{
hit.transform.position = worldPoint;]
}
else if (touch[Input.touchCount-1].phase == TouchPhase.Began)
{
startPos[touch[Input.touchCount-1].fingerId] = worldPoint;
}
else if (touch[Input.touchCount-1].phase == TouchPhase.Ended)
{
hit.transform.position = startPos[touch[Input.touchCount-1].fingerId];
}
}
}
}
what can i do for drag faster without gameobject will released? sorry for my bad english
one solution is to play with a bool variable and tag,
you keep in memory the gameobject you are dragging, you set a bool variable to true.. this is the idea , you try to use bool variable instead touchphase.ended/began...
this post could help you
i have just adapted to game2D
GameObject objet = null;
Plane plane;
float rayDistance;
Vector3 Offset;
bool mouseOver = false;
bool mousePressed = false;
void FixedUpdate()
{
if (Input.touchCount > 0)
{
mousePressed = true;
}
else
{
mousePressed = false;
objet = null;
}
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(touch[Input.touchCount - 1].position);
RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero, Mathf.Infinity);
if (hit.transform != null && hit.collider.tag == "Draggable")
{
mouseOver = true;
if (Input.GetTouch(0).phase != TouchPhase.Moved)
objet = hit.collider.gameObject;
}
else
{
if (mousePressed == false)
mouseOver = false;
}
if (mouseOver)
{
if (mousePressed)
{
//to adapt following your game configuration
plane = new Plane(Camera.main.transform.forward * -1, objet.transform.position);
plane.Raycast(ray, out rayDistance);
objet.transform.position = ray.GetPoint(rayDistance);// + Offset; to see if offset is needed
}
}
} // end update

Player doesn't move after being spawned

I'm currently working on a tactical RPG and I have the following issue:
When the player is destroyed, he is spawned at a specific position in the grid. However, after being spawned he doesn't move.
I'm using this script to destroy the player and spawn him. It's attached to each player in the game:
using System.Collections.Generic;
using UnityEngine;
public class Jogador : MonoBehaviour
{
[SerializeField] private Mapa mapa;
public Vector2Int GridPosition;
public bool isPlayer = false;
public float Health = 50f;
public GameObject SpawnPoint;
private void Awake()
{
if (!mapa) mapa = FindObjectOfType<Mapa>();
}
// Start is called before the first frame update
void Start()
{
foreach (var tile in mapa.GridMatriz)
{
//tile.jogador = this;
}
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit) && hit.transform == this.transform)
{
mapa.GetComponent<Movimentação>().TurnEnd();
isPlayer = true;
mapa.GetComponent<Movimentação>().TurnStart();
Debug.Log("clicked");
}
}
CheckHealth();
}
public void CheckHealth()// Function to check the player's health
{
if (Health <= 0)
{
Destroy(gameObject);
Instantiate(this, Spawnador.transform.position, Quaternion.identity);
}
}
}
This is the movement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Movimentação : 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, SpawBala.transform.rotation);
Rigidbody BalaRigid = tiro.GetComponent<Rigidbody>();
if (SpawBala.tag == "Bala1")
{
BalaRigid.AddForce(Vector3.forward * ProjetilVeloc);
}
if (SpawBala.tag == "Bala2")
{
BalaRigid.AddForce(Vector3.back * 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;
}
}
}
I really don't know what's going on guys.

touch control to move cube (in an array that generates them) left and right

I am moving an object that consists of two cubes: left and right. These cubes are randomly generated on the y-axis upwards.
I am able to move them left and right with no problem, however, when I move one of the cubes left or right they all move.
How am I able to only move one of the cubes when touched only left or right rather than all of them? Here is my code below:
Generate cubes code:
public Transform block;
public Transform player;
private float objectSpawnedTo = 5.0f;
public static float distanceBetweenObjects = 5.0f;
private float nextCheck = 0.0f;
private ArrayList objects = new ArrayList();
void Start () {
maintenance(0.0f);
}
void Update () {
float playerX = player.position.y;
if(playerX > nextCheck)
{
maintenance(playerX);
}
}
private void maintenance(float playerX)
{
nextCheck = playerX + 30;
for (int i = objects.Count-1; i >= 0; i--)
{
Transform blck = (Transform)objects[i];
if(blck.position.y < (transform.position.y - 30))
{
Destroy(blck.gameObject);
objects.RemoveAt(i);
}
}
spawnObjects(5);
}
private void spawnObjects(int howMany)
{
float spawnX = objectSpawnedTo;
for(int i = 0; i<howMany; i++)
{
Vector3 pos = new Vector3(-3.5f,spawnX, 0);
//float firstRandom = Random.Range(-6.0f, 1.0f);
Transform blck = (Transform)Instantiate(block, pos, Quaternion.identity);
//blck.localScale+=new Vector3(firstRandom*2,0,0);
objects.Add(blck);
//pos = new Vector3(0,spawnX, 0);
//blck = (Transform)Instantiate(block, pos, Quaternion.identity);
//blck.localScale +=new Vector3((8.6f-firstRandom)*2,0,0);
//objects.Add(blck);
spawnX = spawnX + distanceBetweenObjects;
}
objectSpawnedTo = spawnX;
}
}
Cube-control code:
public float speed = 5;
// Use this for initialization
void Start () {
}
void Update() {
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
// Get movement of the finger since last frame
Vector3 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
// Move object across XY plane
transform.Translate(touchDeltaPosition.x * speed, 0, 0);
Vector3 boundaryVector = transform.position;
boundaryVector.x = Mathf.Clamp (boundaryVector.x, -5.5f, -2.8f);
transform.position = boundaryVector;
}
}
}
The problem is your cube-control code has no condition in it about which cube is selected : you simply wait for Input.touchCount to be > 0 and then move the cube. So all the cube having this script will move.
I think what you need to do is a raycast to check which cube has been "touched" and then only move it if raycast is successful :
[SerializeField]
private float speed = 0.5f;
private int MAX_TOUCH_COUNT = 5;
private bool[] touched;
protected void Start()
{
touched = new bool[MAX_TOUCH_COUNT];
}
void Update()
{
if (Input.touchCount > 0)
{
for(int i = 0; i < (Input.touchCount <= MAX_TOUCH_COUNT ? Input.touchCount : MAX_TOUCH_COUNT); i++)
{
if(touched[i] && Input.GetTouch(i).phase == TouchPhase.Ended)
{
touched[i] = false;
}
else if (!touched[i] && Input.GetTouch(i).phase == TouchPhase.Began)
{
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(i).position);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo))
{
if (hitInfo.transform.GetComponentInChildren<*YOUR_CUBE_CONTROL_CLASS_NAME*>() == this)
{
touched[i] = true;
}
}
}
else if (touched[i] && Input.GetTouch(i).phase == TouchPhase.Moved)
{
// Get movement of the finger since last frame
Vector3 touchDeltaPosition = Input.GetTouch(i).deltaPosition;
// Move object across XY plane
transform.Translate(touchDeltaPosition.x * speed, 0, 0);
Vector3 boundaryVector = transform.position;
boundaryVector.x = Mathf.Clamp (boundaryVector.x, -5.5f, -2.8f);
transform.position = boundaryVector;
}
}
else
{
touched = false;
}
}
}
Hope this help,

RayCast in unity C#

I'm trying to use a raycast in unity that only reflect off of an objects i define but it didn't work with me any help please?
my game is laser reflection so it's not like a shooting game i need the laser to be visible the whole time and i only Need the laser to be reflected off of the mirrors and not the walls, not the floor nor the other objects in the room.
i tried this code.
public class RaycastReflection : MonoBehaviour
{
public int gunDamage = 1;
public float hitForce = 1f;
private Transform goTransform;
private LineRenderer lineRenderer;
private Ray ray;
private RaycastHit hit;
private Vector3 inDirection;
public int nReflections = 2;
private int nPoints;
void Awake()
{
}
void Update()
{
nReflections = Mathf.Clamp(nReflections, 1, nReflections);
ray = new Ray(goTransform.position, goTransform.forward);
nPoints = nReflections;
lineRenderer.SetVertexCount(nPoints);
lineRenderer.SetPosition(0, goTransform.position);
for (int i = 0; i <= nReflections; i++)
{
//If the ray hasn't reflected yet
if (i == 0)
{
//cast the ray 100 units at the specified direction
if (Physics.Raycast(ray.origin, ray.direction, out hit, 100))
{
inDirection = Vector3.Reflect(ray.direction, hit.normal);
ray = new Ray(hit.point, inDirection);
if (nReflections == 1)
{
lineRenderer.SetVertexCount(++nPoints);
}
lineRenderer.SetPosition(i + 1, hit.point);
}
}
else
{
if (Physics.Raycast(ray.origin, ray.direction, out hit, 100))
{
Target health = hit.collider.GetComponent<Target>()
if (health != null)
health.Damage(gunDamage);
if (hit.rigidbody != null)
hit.rigidbody.AddForce(-hit.normal * hitForce);
inDirection = Vector3.Reflect(inDirection, hit.normal);
ray = new Ray(hit.point, inDirection);
lineRenderer.SetVertexCount(++nPoints);
lineRenderer.SetPosition(i + 1, hit.point);
}
}
}
}
}

Categories