Player doesn't move after being spawned - c#

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.

Related

Move Object Using Raycast

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;
}
}
} }

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);
}
}
}
}
}

Move a player along Y axis using touch location

I'm trying to move a player when the screen is tapped to where the screen is tapped, but only along the Y axis. I've tried this:
Vector2 touchPosition;
[SerializeField] float speed = 1f;
void Update() {
for (var i = 0; i < Input.touchCount; i++) {
if (Input.GetTouch(i).phase == TouchPhase.Began) {
// assign new position to where finger was pressed
transform.position = new Vector3 (transform.position.x, Input.GetTouch(i).position.y, transform.position.z);
}
}
}
But the player disappears rather than moves. What am I doing wrong?
You need to convert the touch position from Screen to World. This is very easy to do, I've just knocked this quick script together, hopefully it helps:
using UnityEngine;
using System.Collections;
public class TouchSomething : MonoBehaviour
{
public GameObject thingToMove;
public float smooth = 2;
private Vector3 _endPosition;
private Vector3 _startPosition;
private void Awake()
{
_startPosition = thingToMove.transform.position;
}
private void Update()
{
if(Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer)
{
_endPosition = HandleTouchInput();
}
else
{
_endPosition = HandleMouseInput();
}
thingToMove.transform.position = Vector3.Lerp(thingToMove.transform.position, new Vector3(_endPosition.x, _endPosition.y, 0), Time.deltaTime * smooth);
}
private Vector3 HandleTouchInput()
{
for (var i = 0; i < Input.touchCount; i++)
{
if (Input.GetTouch(i).phase == TouchPhase.Began)
{
var screenPosition = Input.GetTouch(i).position;
_startPosition = Camera.main.ScreenToWorldPoint(screenPosition);
}
}
return _startPosition;
}
private Vector3 HandleMouseInput()
{
if(Input.GetMouseButtonDown(0))
{
var screenPosition = Input.mousePosition;
_startPosition = Camera.main.ScreenToWorldPoint(screenPosition);
}
return _startPosition;
}
}
This allows you to also test in the editor as well.
I hope this helps.

How to make Bullet initiate from the direction the player is in

I am making 2D game in Unity.
In this I wanted to add a bullet with a limited number of shots.
The bullet fires in the direction in which the player is but always initiate from the right side even if the player is facing left side. And I have limited the bullet count to 3.
How do I put delay in between the occurrence of the bullets?
1st Script (Bullet)
public class Bullet : MonoBehaviour {
private Player player;
public float speed = 1f;
public int abc = 2;
// Use this for initialization
void Start () {
player = GameObject.Find ("Player").GetComponent<Player> ();
if (player.aa.x == transform.localScale.x)
abc = 1;
}
// Update is called once per frame
public void Update () {
if (abc == 1)
rigidbody2D.velocity = new Vector3 (transform.localScale.x, 0, 1) * speed;
else
rigidbody2D.velocity = new Vector3 (transform.localScale.x, 0, 1) * speed;
}
}
2nd Script (Player)
public class Player : MonoBehaviour {
public float speed = 10f;
public Vector2 maxVelocity = new Vector2(3, 5);
public bool standing;
public float jetSpeed = 15f;
public float airSpeedMultiplier = .3f;
public AudioClip leftFootSound;
public AudioClip rightFootSound;
public AudioClip thudSound;
public AudioClip rocketSound;
public Vector3 aa = new Vector3(1,1,1);
private Animator animator;
private PlayerController controller;
void Start(){
controller = GetComponent<PlayerController> ();
animator = GetComponent<Animator> ();
}
void PlayLeftFootSound(){
if (leftFootSound)
AudioSource.PlayClipAtPoint (leftFootSound, transform.position);
}
void PlayRightFootSound(){
if (rightFootSound)
AudioSource.PlayClipAtPoint (rightFootSound, transform.position);
}
void PlayRocketSound(){
if (!rocketSound || GameObject.Find ("RocketSound"))
return;
GameObject go = new GameObject ("RocketSound");
AudioSource aSrc = go.AddComponent<AudioSource> ();
aSrc.clip = rocketSound;
aSrc.volume = 0.7f;
aSrc.Play ();
Destroy (go, rocketSound.length);
}
void OnCollisionEnter2D(Collision2D target){
if (!standing) {
var absVelX = Mathf.Abs(rigidbody2D.velocity.x);
var absVelY = Mathf.Abs(rigidbody2D.velocity.y);
if(absVelX <= .1f || absVelY <= .1f){
if(thudSound)
AudioSource.PlayClipAtPoint(thudSound, transform.position);
}
}
}
// Update is called once per frame
void Update () {
var forceX = 0f;
var forceY = 0f;
var absVelX = Mathf.Abs (rigidbody2D.velocity.x);
var absVelY = Mathf.Abs (rigidbody2D.velocity.y);
if (absVelY < .2f)
standing = true;
else
standing = false;
if (controller.moving.x != 0) {
if (absVelX < maxVelocity.x) {
forceX = standing ? speed * controller.moving.x : (speed * controller.moving.x * airSpeedMultiplier);
aa = transform.localScale = new Vector3 (forceX > 0 ? 1 : -1, 1, 1);
}
animator.SetInteger ("AnimState", 1);
} else {
animator.SetInteger ("AnimState", 0);
}
if (controller.moving.y > 0) {
PlayRocketSound();
if (absVelY < maxVelocity.y)
forceY = jetSpeed * controller.moving.y;
animator.SetInteger ("AnimState", 2);
} else if (absVelY > 0) {
animator.SetInteger("AnimState", 3);
}
rigidbody2D.AddForce (new Vector2 (forceX, forceY));
}
}
3rd Script (PlayerController)
public class PlayerController : MonoBehaviour {
public Vector2 moving = new Vector2();
public int Bulletlimit = 0;
public int MaxBulletlimit = 3;
public float bulletDelay = 3f;
public bool Gun;
public Bullet bullet;
// Use this for initialization
void Start () {}
// Update is called once per frame
void Update () {
moving.x = moving.y = 0;
if (Input.GetKey ("right")) {
moving.x = 1;
} else if (Input.GetKey ("left")) {
moving.x = -1;
}
if (Input.GetKey ("up")) {
moving.y = 1;
} else if (Input.GetKey ("down")) {
moving.y = -1;
}
if (Input.GetKey ("s")) {
if(Gun){
if(Bulletlimit < MaxBulletlimit)
{
Bullet clone = Instantiate (bullet, transform.position, Quaternion.identity) as Bullet;
Bulletlimit = Bulletlimit + 1;
}
}
}
}
public void BulletCount() {
Bulletlimit = Bulletlimit - 1;
}
}
1) There is an easy method to know where to position your bullets and which direction to shoot. Add a child dummy gameobject under your character that will be used as bullet's initial position. Position it where you want. Now this gameobject moves and rotates relative to your character. Use it's transform.position and transform.rotation.forward when you instantiate bullets.
2) Keep current time when user fired a bullet in a variable like private float lastShotTime;. Update it's value when you fired a bullet lastShotTime = Time.time. Then when user wants to shoot another bullet, check if enough time has passed since last shot if (Time.time > lastShotTime + fireDelay) { Shoot(); }.

Categories