Unity 2d Character moves and jumps to specific positions with UI buttons - c#

In a simple 2d project in which my player can move to the right and left on x and can also jump to the right and left in height with two other buttons. The problem is, that the player is not supposed to move freely. By pressing one of the buttons the player should only go to the next specific point, so that the player always stops at six different positions on x (while on y he is free and as high as the platform he is currently standing on). To be able to jump realistically, the player must have gravity and a collider to be able to land on the platforms (and move single platforms horizontal).
Thanks to the tutorial which #TEEBQNE linked in the comments I could finally realise this with Unitys Rigidbody2D and the following script. The problem is that the gravity is now behaving strangely. The player only moves down very slowly and in the process pushes Gameobjects underneath it through others. The player has a Dynamic Rigidbody2D with a gravity scale of 2 and a capsule collider 2d. Is that a problem with the script or with the components in the players inspector?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movePlayer : MonoBehaviour
{
public GameObject posChecker1;
public GameObject posChecker2;
public GameObject posChecker3;
public GameObject posChecker4;
public GameObject posChecker5;
public GameObject posChecker6;
public bool go; //Player is allowed to move
public bool grounded; //Player is allowed to jump
public string moveDirection;
public float horizVel = 0; //Movement along x
public float verticVel = 0; //Jump
public int laneNum = 3; //Player starts on lane 3!!
public bool rightButtonMove = false;//
public bool leftButtonMove = false;//
public bool rightButtonJump = false;//
public bool leftButtonJump = false;//
//Animation
private SpriteRenderer spriteRenderer;
private Animator animator;
private void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
animator = GetComponent<Animator>();
}
// Start is called before the first frame update
void Start()
{
posChecker1.SetActive(true);//GameObject.Find("PositionChecker1").SetActive(true);
posChecker2.SetActive(true);
posChecker3.SetActive(true); //Player start on lane 3!!
posChecker4.SetActive(true);
posChecker5.SetActive(true);
posChecker6.SetActive(true);
laneNum = 3;
go = true;
}
// Update is called once per frame
void Update()
{
//Raycast
int playerMask = LayerMask.GetMask("PositionChecker");// !!!
Debug.DrawRay(transform.position, transform.TransformDirection(Vector2.up) * 50f, Color.green);
RaycastHit2D hitCheck = Physics2D.Raycast(transform.position, transform.TransformDirection(Vector2.up), 50f, playerMask);
//Only the checker objects in the rows next to the player are active
if (laneNum == 1)
{
posChecker1.SetActive(false);
posChecker2.SetActive(true);
}
else if (laneNum == 2)
{
posChecker1.SetActive(true);
posChecker2.SetActive(false);
posChecker3.SetActive(true);
}
else if (laneNum == 3)
{
posChecker2.SetActive(true);
posChecker3.SetActive(false);
posChecker4.SetActive(true);
}
else if (laneNum == 4)
{
posChecker3.SetActive(true);
posChecker4.SetActive(false);
posChecker5.SetActive(true);
}
else if (laneNum == 5)
{
posChecker4.SetActive(true);
posChecker5.SetActive(false);
posChecker6.SetActive(true);
}
else if (laneNum == 6)
{
posChecker5.SetActive(true);
posChecker6.SetActive(false);
}
//Movement
GetComponent<Rigidbody2D>().velocity = new Vector3(horizVel, verticVel, 0);
//Raycast
if (hitCheck)
{
if (moveDirection == "l" && horizVel != 0)
{
laneNum -= 1;
}
if (moveDirection == "r" && horizVel != 0)
{
laneNum += 1;
}
go = true;
horizVel = 0;
verticVel = 0;
grounded = true;
}
if (horizVel == 0)
moveDirection = "";
//Animation
bool flipSprite = (spriteRenderer.flipX ? (horizVel > 0.01f) : (horizVel < 0.01f));
if (flipSprite)
{
spriteRenderer.flipX = !spriteRenderer.flipX;
}
animator.SetBool("grounded", grounded); // -->Jump
animator.SetFloat("velocityX", Mathf.Abs(horizVel));
}
//Button Input
public void RightButton() //
{
if (laneNum < 6 && go)
{
moveDirection = "r";
go = false;
horizVel = 4;
}
}
public void LeftButton()//
{
if (laneNum > 1 && go)
{
moveDirection = "l";
go = false;
horizVel = -4;
}
}
public void RightJump()//
{
if (laneNum < 6 && grounded && go)
{
moveDirection = "r";
horizVel = 4;
verticVel = 7;
go = false;
grounded = false;
}
}
public void LeftJump()//
{
if (laneNum > 1 && grounded && go)
{
moveDirection = "l";
horizVel = -4;
verticVel = 7;
go = false;
grounded = false;
}
}
}

Glad I was able to help in some way and that you figured out your issue!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movePlayer : MonoBehaviour
{
//Player Position x
public GameObject posChecker1;
public GameObject posChecker2;
public GameObject posChecker3;
public GameObject posChecker4;
public GameObject posChecker5;
public GameObject posChecker6;
public int laneNum = 3; //Player starts on lane 3!!
//Player Position y
public float yPos1;
public float yPos2;
public Transform player;
//Movement Variables
public bool go; //Player is allowed to move
public bool grounded; //Player is allowed to jump
public string moveDirection;
public float horizVel = 0; //Movement along x
public float verticVel = 0; //Jump
//Animation
private SpriteRenderer spriteRenderer;
private Animator animator;
private void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
animator = GetComponent<Animator>();
}
// Start is called before the first frame update
void Start()
{
posChecker1.SetActive(true);//GameObject.Find("PositionChecker1").SetActive(true);
posChecker2.SetActive(true);
posChecker3.SetActive(true); //Player start on lane 3!!
posChecker4.SetActive(true);
posChecker5.SetActive(true);
posChecker6.SetActive(true);
laneNum = 3;
go = true;
}
// Update is called once per frame
void Update()
{
//Raycast
int playerMask = LayerMask.GetMask("PositionChecker");// !!!
Debug.DrawRay(transform.position, transform.TransformDirection(Vector2.up) * 50f, Color.green);
RaycastHit2D hitCheck = Physics2D.Raycast(transform.position, transform.TransformDirection(Vector2.up), 50f, playerMask);
//Only the checker objects in the rows next to the player are active
if (laneNum == 1)
{
posChecker1.SetActive(false);
posChecker2.SetActive(true);
}
else if (laneNum == 2)
{
posChecker1.SetActive(true);
posChecker2.SetActive(false);
posChecker3.SetActive(true);
}
else if (laneNum == 3)
{
posChecker2.SetActive(true);
posChecker3.SetActive(false);
posChecker4.SetActive(true);
}
else if (laneNum == 4)
{
posChecker3.SetActive(true);
posChecker4.SetActive(false);
posChecker5.SetActive(true);
}
else if (laneNum == 5)
{
posChecker4.SetActive(true);
posChecker5.SetActive(false);
posChecker6.SetActive(true);
}
else if (laneNum == 6)
{
posChecker5.SetActive(true);
posChecker6.SetActive(false);
}
//Movement
if (grounded)
{
verticVel = GetComponent<Rigidbody2D>().velocity.y;
}
GetComponent<Rigidbody2D>().velocity = new Vector3(horizVel, /*GetComponent<Rigidbody2D>().velocity.y*/verticVel, 0);
//Jump
yPos2 = player.transform.position.y;
if ((yPos2 - 2) >= yPos1 && !grounded)
{
if (moveDirection == "l")
horizVel = -4;
if (moveDirection == "r")
horizVel = 4;
verticVel = verticVel * 0.95f;
}
//Raycast
if (hitCheck)
{
if (moveDirection == "l" && horizVel != 0)
{
laneNum -= 1;
}
if (moveDirection == "r" && horizVel != 0)
{
laneNum += 1;
}
go = true;
horizVel = 0;
verticVel = 0;
grounded = true;
}
if (horizVel == 0 && grounded)
moveDirection = "";
//Animation
bool flipSprite = (spriteRenderer.flipX ? (horizVel > 0.01f) : (horizVel < 0.01f));
if (flipSprite)
{
spriteRenderer.flipX = !spriteRenderer.flipX;
}
animator.SetBool("grounded", grounded); // -->Jump
animator.SetFloat("velocityX", Mathf.Abs(horizVel));
}
//Button Input
public void RightButton() //
{
if (laneNum < 6 && go)
{
moveDirection = "r";
go = false;
horizVel = 4;
}
}
public void LeftButton()//
{
if (laneNum > 1 && go)
{
moveDirection = "l";
go = false;
horizVel = -4;
}
}
public void RightJump()//
{
if (laneNum < 6 && grounded && go)
{
moveDirection = "r";
verticVel = 5;
go = false;
grounded = false;
//
yPos1 = player.transform.position.y;
Debug.Log(yPos1);
//
}
}
public void LeftJump()//
{
if (laneNum > 1 && grounded && go)
{
moveDirection = "l";
verticVel = 5;
go = false;
grounded = false;
//
yPos1 = player.transform.position.y;
Debug.Log(yPos1);
//
}
}
}

Related

How do I get the Enemy to pickup the closet weapon after running out of ammo?

I am trying to create an enemy that is 'smart', that changes a weapon if it has no ammo left and if all its weapons are depleted of ammo find the nearest weapon and change the weapon.
So far, I have an enemy that can patrol, find player in range, chase and attack the player.
Here is the code:
public class EnemyControler : MonoBehaviour
{
[Header("Attack")]
[SerializeField] float shootingDistance =10.0f;
[SerializeField] float shootDelay = 3.5f;
[Range(0,1.0f)][SerializeField] float shootingAccuracy =0.5f;
[SerializeField] int shootDamage =5;
[SerializeField] int ammo = 1;
[Header("User Interface")]
public Transform canvasTr;
public Slider Healthbar;
[Header("Health/Damage/Death")]
public float MaxHealth;
public float Damage;
public float AttackRange;
public int deathCounter;
public Transform ammoObject;
private NavMeshAgent navAgent;
private Collider enemycollider;
private Transform PlayerTr;
private Animator EnemyAnim;
float Health;
bool showingHealthBar, alive;
bool isPatrolling =false;
bool isInShootingRange =false;
bool canResumeIdleState =true;
bool isPreparingToShoot=false;
bool isDead =false;
bool isAlerted =false;
float shootTimer = Mathf.Infinity;
AIPatrolBehavior aIPatrolBehavior = null;
void Start()
{
Health = MaxHealth;
canvasTr.gameObject.SetActive(false);
navAgent = GetComponent<NavMeshAgent>();
EnemyAnim = GetComponent<Animator>();
enemycollider = GetComponent<Collider>();
PlayerTr = GameObject.FindGameObjectWithTag("Player").transform;
aIPatrolBehavior = GetComponent<AIPatrolBehavior>();
alive = true;
ammo = 100;
StartCoroutine(Idle());
// are you sure you want to randomly change MaxHealth after settting health = maxHealth?
//the slider gets weirdly bugged
// MaxHealth = Random.Range(50, 200);
Healthbar.maxValue = MaxHealth; // set the max value to MaxHelth
}
private void Update()
{
if(isDead)return;
if(Vector3.Distance(PlayerTr.transform.position, transform.position) > 20 && !isAlerted
|| PlayerTr.GetComponent<PlayerController>().HealthBar.value <= 0.0f){
StopAllCoroutines();
GetComponent<AIPatrolBehavior>().enabled =true;
return;
}
if(Vector3.Distance(PlayerTr.transform.position, transform.position) < 20 && isAlerted) isAlerted=false;
isInShootingRange = DistanceToPlayer() < shootingDistance &&
DistanceToPlayer() > AttackRange - 0.5f &&
PlayerTr.GetComponent<PlayerController>().HealthBar.value > 0;
if(isInShootingRange)
{
if(canResumeIdleState){
StopAllCoroutines();
canResumeIdleState=false;
}
ProcessShooting();
} else{
if(!canResumeIdleState){
isPreparingToShoot =false;
StartCoroutine(Idle());
canResumeIdleState =true;
navAgent.enabled =true;
}
}
}
private void ProcessShooting()
{
if(!isPreparingToShoot) shootTimer +=Time.deltaTime;
navAgent.enabled =false;
transform.LookAt(PlayerTr);
float randomProbability =Random.Range(0,1.0f);
if(shootTimer > shootDelay){
ShootAtPlayer();
}
EnemyAnim.SetFloat("MovmentSpeed", 0, 0.3f, Time.deltaTime);
}
private void ShootAtPlayer(){
if(isPreparingToShoot)return;
EnemyAnim.SetBool("PrepareAttack", false);
shootTimer =0.0f;
isPreparingToShoot = true;
EnemyAnim.SetTrigger("shoot");
}
public void ShootPlayerAnimationEvent(){
Debug.Log("Player got shot");
float randomAccuracy = Random.Range(0, 1.0f);
bool willHitTarget = randomAccuracy > 1.0f - shootingAccuracy;
if(willHitTarget && DistanceToPlayer() < shootingDistance){
PlayerTr.GetComponent<PlayerController>().DoDamage(shootDamage,true);
}
GetComponentInChildren<AIWeapon>().UseWeapon();
isPreparingToShoot =false;
}
IEnumerator Idle()
{
EnemyAnim.SetBool("PrepareAttack", false);
yield return new WaitUntil(() => Vector3.Distance(PlayerTr.transform.position, transform.position) < 20 || isAlerted);
StartCoroutine(RunToTarget());
}
IEnumerator RunToTarget()
{
aIPatrolBehavior.enabled =false;
if(navAgent.isOnNavMesh) { // save from error apperng
navAgent.isStopped = false;
}
EnemyAnim.SetTrigger("Attack");
while (Vector3.Distance(PlayerTr.transform.position, transform.position) > AttackRange - 0.5f)
{
if(navAgent.isOnNavMesh) { // save from error apperng
navAgent.SetDestination(PlayerTr.position);
}
// navAgent.SetDestination(PlayerTr.position);
EnemyAnim.SetFloat("MovmentSpeed", 1, 0.3f, Time.deltaTime);
yield return null;
}
StartCoroutine(Attack());
}
IEnumerator Attack()
{
EnemyAnim.SetBool("PrepareAttack", true);
navAgent.isStopped = true;
while (Vector3.Distance(PlayerTr.position, transform.position) < AttackRange)
{
EnemyAnim.SetTrigger("Attack");
float t = 0.5f;
while (t > 0)
{
Vector3 rotation = Vector3.RotateTowards(transform.forward, PlayerTr.position - transform.position, 5f * Time.deltaTime, 1f);
transform.forward = rotation;
t -= Time.deltaTime;
yield return null;
}
yield return null;
}
EnemyAnim.SetBool("PrepareAttack", false);
StartCoroutine(RunToTarget());
}
float DistanceToPlayer(){
return Vector3.Distance(transform.position,PlayerTr.position);
}
public void DoDamage(float damage)
{
Alert();
if (!showingHealthBar)
{
showingHealthBar = true;
StartCoroutine(ShowHealthBar());
}
Health -= damage;
Debug.Log("Health: " + Health + " of: " + MaxHealth);
Healthbar.value = Health;
if (Health <= 0)
{
StopAllCoroutines();
if(navAgent.isOnNavMesh) { // save from error apperng
navAgent.isStopped = true;
}
if (alive)
{
alive = true; // does this make sense?
StartCoroutine(Death());
}
}
}
I have tried searching through Google to find any tutorials, but without success. Does anyone have any ideas?
if the weapons placed on constant places all over the map, you can make the enemy stop patrolling or chasing the player when his ammo == 0 by a Boolean then use MoveTowrds() the weapon.
and u can include some way to calculate the distance between the enemy's position and all the weapons on the array, then it head for the closest.
you will use an array of vectors to store the locations of weapons.
now its your turn to try.

Platformer Double-Jump and Dash Not Working

Working on a platformer where as the player moves over an energy orb, they can choose to fuel either a double jump or a dash. No errors according to unity, but when I press the corresponding keys for my double jump and dash, neither work. Simply nothing happens. Oh and btw my character randomly freezes and I have to tap the movement key again to get him to continue moving this is also a new issue so may be related. I am very new to all this.
public class playerMovement : MonoBehaviour
{
[SerializeField] private float speed;
[SerializeField] int dashEnergy = 1;
[SerializeField] int doubleJumpEnergy = 1;
private Rigidbody2D body;
private Animator anim;
private int jumpCount;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
}
private void Update()
{
//Left-Right Movement
float horizontalInput = Input.GetAxis("Horizontal");
if(Input.GetKey(KeyCode.Space) && jumpCount == 0)
{
jump();
jumpCount += 1;
}
body.velocity = new Vector2(horizontalInput*speed, body.velocity.y);
//Character Turns Towards Movement Direction
if (horizontalInput > 0.01f)
transform.localScale = new Vector3(-5, 5, 5);
if (horizontalInput < -0.01f)
transform.localScale = new Vector3(5,5,5);
//Dash & doubleJump
void doubleJump()
{
if(Input.GetKey(KeyCode.Space)&&jumpCount==1 && doubleJumpEnergy==1)
{
jump();
doubleJumpEnergy -= 1;
}
}
void Dash()
{
if(Input.GetKey(KeyCode.LeftShift) && dashEnergy == 1)
{
body.velocity = new Vector2(horizontalInput*speed*60, body.velocity.y);
dashEnergy -=1;
}
}
}
public void jump()
{
body.velocity = new Vector2(body.velocity.x, speed);
}
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag == "EnergyBubble" && Input.GetKey(KeyCode.V))
{
dashEnergy += 1;
}
if(collision.gameObject.tag == "EnergyBubble" && Input.GetKey(KeyCode.C))
{
doubleJumpEnergy += 1;
}
if (collision.gameObject.tag == "Ground")
{
jumpCount=0;
}
}
}
Firstly, all physics operations should be used from fixedUpdate method, for example:
void FixedUpdate()
{
if (Input.GetButtonDown("Space"))
rb.velocity = new Vector2(0, 10);
}
It's needs for smoothly physics movement.
Or call your own method from it:
void FixedUpdate()
{
if (Input.GetButtonDown("Space"))
jump();
}
Then you have a bug in condition check statements, you have to use:
//Dash & doubleJump
if (Input.GetKey(KeyCode.Space) && jumpCount == 1 && doubleJumpEnergy >= 1)
{
body.velocity = new Vector2(0, 2);
doubleJumpEnergy -= 1;
}
if (Input.GetKey(KeyCode.LeftShift) && dashEnergy >= 1)
{
body.velocity = new Vector2(horizontalInput * speed * 60, body.velocity.y);
dashEnergy -= 1;
}
Problem with a condition check statements, you need to have ">=" operator: dashEnergy >= 1 and doubleJumpEnergy >= 1 instead ==

How to make the turret that shoot laser to targets to choose the closet target each time and shoot the laser towards the closet target?

For example there are 5 target and they are moving randomly around the turret.
Now i'm using only one target targets[0] and the turret is rotating facing the target and shoot laser to it.
Now i want to make it with multiple targets and that the turret will choose each time the closet target and will shoot to it the laser.
I changed this part added a for loop over the targets :
for (int i = 0; i < targets.Count; i++)
but i'm still using only one target, targets[0] i'm not sure how to add the distance part and the closet target choosing.
I tried this solution but now the turret(transform) is not rotating at all towards the selected target. for some reason this two lines return null on the closestTarget :
RotateToMouseDirection(gameObject, closestTarget.position);
The script with the changes :
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System;
using UnityEngine;
public class Hovl_DemoLasers : MonoBehaviour
{
public List<Transform> targets;
public GameObject FirePoint;
public Camera Cam;
public float MaxLength;
public GameObject[] Prefabs;
private Ray RayMouse;
private Vector3 direction;
private Quaternion rotation;
[Header("GUI")]
private float windowDpi;
private int Prefab;
private GameObject Instance;
private Hovl_Laser LaserScript;
private Hovl_Laser2 LaserScript2;
private bool rotateMouse = true;
private bool startLaser = true;
private float buttonSaver = 0f;
private Hovl_LaserDemo hovl_laserDemo;
private float maxDistance = 0;
private float distance;
private Transform closestTarget;
void Start ()
{
if (Screen.dpi < 1) windowDpi = 1;
if (Screen.dpi < 200) windowDpi = 1;
else windowDpi = Screen.dpi / 200f;
Counter(0);
}
void Update()
{
//Enable lazer
if (Input.GetMouseButtonDown(0))
{
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
rotateMouse = true;
}
if (Input.GetMouseButtonDown(1))
{
rotateMouse = false;
}
//Disable lazer prefab
if (Input.GetMouseButtonUp(0))
{
/*if (LaserScript) LaserScript.DisablePrepare();
if (LaserScript2) LaserScript2.DisablePrepare();
Destroy(Instance,1);*/
}
if ((Input.GetKey(KeyCode.A) || Input.GetAxis("Horizontal") < 0) && buttonSaver >= 0.4f)// left button
{
buttonSaver = 0f;
Counter(-1);
}
if ((Input.GetKey(KeyCode.D) || Input.GetAxis("Horizontal") > 0) && buttonSaver >= 0.4f)// right button
{
buttonSaver = 0f;
Counter(+1);
}
buttonSaver += Time.deltaTime;
if (startLaser)
{
rotateMouse = false;
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
hovl_laserDemo = Instance.GetComponent<Hovl_LaserDemo>();
startLaser = false;
}
if (targets != null)
{
for (int i = 0; i < targets.Count; i++)
{
distance = Vector3.Distance(transform.position, targets[i].position);
if (distance < maxDistance)
{
maxDistance = distance;
closestTarget = targets[i];
}
}
if (hovl_laserDemo != null)
{
MaxLength = distance;
hovl_laserDemo.MaxLength = distance;
}
if (Cam != null)
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, MaxLength))
{
RotateToMouseDirection(gameObject, closestTarget.position);
}
else
{
RotateToMouseDirection(gameObject, closestTarget.position);
}
}
}
if (Cam != null && rotateMouse)
{
RaycastHit hit;
var mousePos = Input.mousePosition;
RayMouse = Cam.ScreenPointToRay(mousePos);
if (Physics.Raycast(RayMouse.origin, RayMouse.direction, out hit, MaxLength))
{
RotateToMouseDirection(gameObject, hit.point);
}
else
{
var pos = RayMouse.GetPoint(MaxLength);
RotateToMouseDirection(gameObject, pos);
}
}
else
{
Debug.Log("No camera");
}
}
void OnGUI()
{
GUI.Label(new Rect(10 * windowDpi, 5 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use the keyboard buttons A/<- and D/-> to change lazers!");
GUI.Label(new Rect(10 * windowDpi, 20 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use left mouse button for shooting!");
}
void Counter(int count)
{
Prefab += count;
if (Prefab > Prefabs.Length - 1)
{
Prefab = 0;
}
else if (Prefab < 0)
{
Prefab = Prefabs.Length - 1;
}
}
void RotateToMouseDirection (GameObject obj, Vector3 destination)
{
direction = destination - obj.transform.position;
rotation = Quaternion.LookRotation(direction);
obj.transform.localRotation = Quaternion.Lerp(obj.transform.rotation, rotation, 1);
}
}
The old original script before the changes :
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System;
using UnityEngine;
public class DemoLasers : MonoBehaviour
{
public List<Transform> targets;
public GameObject FirePoint;
public Camera Cam;
public float MaxLength;
public GameObject[] Prefabs;
private Ray RayMouse;
private Vector3 direction;
private Quaternion rotation;
[Header("GUI")]
private float windowDpi;
private int Prefab;
private GameObject Instance;
private Hovl_Laser LaserScript;
private Hovl_Laser2 LaserScript2;
private bool rotateMouse = true;
private bool startLaser = true;
private float buttonSaver = 0f;
private Hovl_LaserDemo hovl_laserDemo;
void Start ()
{
if (Screen.dpi < 1) windowDpi = 1;
if (Screen.dpi < 200) windowDpi = 1;
else windowDpi = Screen.dpi / 200f;
Counter(0);
}
void Update()
{
//Enable lazer
if (Input.GetMouseButtonDown(0))
{
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
rotateMouse = true;
}
if (Input.GetMouseButtonDown(1))
{
rotateMouse = false;
}
if ((Input.GetKey(KeyCode.A) || Input.GetAxis("Horizontal") < 0) && buttonSaver >= 0.4f)// left button
{
buttonSaver = 0f;
Counter(-1);
}
if ((Input.GetKey(KeyCode.D) || Input.GetAxis("Horizontal") > 0) && buttonSaver >= 0.4f)// right button
{
buttonSaver = 0f;
Counter(+1);
}
buttonSaver += Time.deltaTime;
if (startLaser)
{
rotateMouse = false;
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
hovl_laserDemo = Instance.GetComponent<Hovl_LaserDemo>();
startLaser = false;
}
if (targets != null)
{
for (int i = 0; i < targets.Count; i++)
{
if (hovl_laserDemo != null)
{
float distance = Vector3.Distance(gameObject.transform.position, targets[0].position);
MaxLength = distance;
hovl_laserDemo.MaxLength = distance;
}
if (Cam != null)
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, MaxLength))
{
RotateToMouseDirection(gameObject, targets[0].position);
}
else
{
RotateToMouseDirection(gameObject, targets[0].position);
}
}
}
}
if (Cam != null && rotateMouse)
{
RaycastHit hit;
var mousePos = Input.mousePosition;
RayMouse = Cam.ScreenPointToRay(mousePos);
if (Physics.Raycast(RayMouse.origin, RayMouse.direction, out hit, MaxLength))
{
RotateToMouseDirection(gameObject, hit.point);
}
else
{
var pos = RayMouse.GetPoint(MaxLength);
RotateToMouseDirection(gameObject, pos);
}
}
else
{
Debug.Log("No camera");
}
}
void OnGUI()
{
GUI.Label(new Rect(10 * windowDpi, 5 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use the keyboard buttons A/<- and D/-> to change lazers!");
GUI.Label(new Rect(10 * windowDpi, 20 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use left mouse button for shooting!");
}
void Counter(int count)
{
Prefab += count;
if (Prefab > Prefabs.Length - 1)
{
Prefab = 0;
}
else if (Prefab < 0)
{
Prefab = Prefabs.Length - 1;
}
}
void RotateToMouseDirection (GameObject obj, Vector3 destination)
{
direction = destination - obj.transform.position;
rotation = Quaternion.LookRotation(direction);
obj.transform.localRotation = Quaternion.Lerp(obj.transform.rotation, rotation, 1);
}
}
Have 2 Variables in a Loop.
one is the index of the current closest target in you List,
and the other one the distance
int closestIndex = 0;
float maxDistance = 0;
for (int i = 0; i < targets.Count; i++)
{
//Here we calculate the distance of the current pos
//You can take any Formula e.g. the Manhattan Formula
float distance = Vector3.Distance(turretPositionOrSth, targets[i].position);
//if the distance is shorter than the current max Distance
if (distance < maxDistance)
{
maxDistance = distance;
closestIndex = i;
}
}
//Now you have your Index in the list to the closest Target,which you can use
//you can use now for example targets[closestIndex] for aiming or so
Also you don't need your already written loop anymore
Here's essentially the same answer as tthe one #cpaech gave, but there was a couple issues.
int closestIndex = 0;
float minDistance = float.MaxValue;
for (int i = 0; i < targets.Count; i++)
{
//Here we calculate the distance of the current pos
//You can take any Formula e.g. the Manhattan Formula
float distance = Vector3.Distance(turretPositionOrSth, targets[i].position);
//if the distance is shorter than the current max Distance
if (distance < maxDistance)
{
maxDistance = distance;
closestIndex = i;
}
}
It could also be helpful to have an attribute for the closest target and have
if (distance < maxDistance)
{
maxDistance = distance;
closestTarget = targets[i];
}
It looks like you have two requirements -- to find not just the closest enemy, but the closest enemy with direct line of sight to the turret?
You could sort the list of enemies by distance to the turret and iterate over it from closest to furthest until a valid target is found (requiring fewer raycasts might provide a small performance advantage if there were a massive number of enemies), or you could just try the raycast on every enemy, but here's a compromise that only tries the raycast if the enemy is closer than any previous enemy tested.
Transform target = null;
float lowestDistance = float.MaxValue;
if( cam != null && hovl_laserDemo != null && targets != null )
{
for( int i = 0; i < targets.Count; i++ )
{
float distance = Vector3.Distance(gameObject.transform.position, targets[i].position);
if( distance < lowestDistance )
{
RaycastHit hit;
if( Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, distance)
&& hit.transform == targets[i] )
{
// If our raycast successfully reached the intended target without being blocked by anything else
lowestDistance = distance;
target = targets[i];
}
}
}
}
if( target != null )
{
MaxLength = lowestDistance;
hovl_laserDemo.MaxLength = lowestDistance;
RotateToMouseDirection(gameObject, target.position);
}
else
{
// Do whatever you want to do when there is no valid target
}
Edit: Actually it looks like your raycast was succeeding if it hit anything, not just the intended target. I've tried to correct that above.

Why does my dash only function properly if you aren't moving?

Here is the complete player controller file.
using UnityEngine;
public class PlayerCont : MonoBehaviour
{
[Header("Movement Variables")]
public float moveSpeed;
private float speed;
public float maxSpeed;
public float acceleration;
public float dropSpeed;
public float slideSpeed;
public int direction = 1;
[Header("Jump Variables")]
public float jumpForce;
public int extraJumps;
private float jumpTimeCounter;
public float jumpTime;
private bool isJumping;
private int jumpNum;
[Header("Dash Variables")]
public float dashSpeed;
public float dashLength = .5f;
public float dashCooldown = 1f;
private float dashCounter;
public float dashCoolCounter;
private KeyCode _lastKeyCode;
private float doubleTapTime = 0.05f;
private bool doubleTap;
public bool isDashing;
public float dashTime;
public float maxDashTime;
[Header("GroundCheck Variables")]
public Transform groundCheck;
public float checkRadius;
public LayerMask whatIsGround;
[Header("Debug Variables")]
public Rigidbody2D rb;
public float moveInputX;
public float moveInputY;
public bool facingRight = true;
public bool isGrounded;
public bool downKey;
public float rbxVel;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
speed = moveSpeed;
jumpNum = extraJumps;
}
void FixedUpdate()
{
}
// Update is called once per frame
void Update()
{
moveInputX = Input.GetAxisRaw("Horizontal");
moveInputY = Input.GetAxisRaw("Vertical");
isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, whatIsGround);
KeyChecks();
Jump();
GroundPound();
Move();
Dash();
}
void KeyChecks()
{
//restricts movement in Y to only be downward
if (moveInputY > 0)
{
moveInputY = 0;
}
//checks for player drop
if (!isGrounded && moveInputY < 0)
{
downKey = true;
}
else
{
downKey = false;
}
//changes direction relative to keypress
if (Input.GetKeyDown(KeyCode.A))
{
direction = -1;
}
if (Input.GetKeyDown(KeyCode.D))
{
direction = 1;
}
}
void Jump()
{
//sets jump number to user specified amount after touching ground
if (isGrounded)
{
extraJumps = jumpNum;
}
//jumps and decrements extrajumps by 1
if (Input.GetKeyDown(KeyCode.Space) && !downKey && extraJumps > 0)
{
isJumping = true;
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
extraJumps--;
}
//basic jump off of ground
else if (Input.GetKeyDown(KeyCode.Space) && extraJumps == 0 && isGrounded && !downKey)
{
isJumping = true;
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
}
//checks for longkeypress of spacebar and increases length of jump
if (Input.GetKey(KeyCode.Space) && extraJumps > 1 && isJumping) // allows a hold down increase to jump while grounded
{
if (jumpTimeCounter > 0)
{
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
jumpTimeCounter -= Time.deltaTime;
}
else
{
jumpTimeCounter = jumpTime;
isJumping = false;
}
}
}
void GroundPound()
{
//ground pound keypress check
if (!isGrounded && Input.GetKeyDown(KeyCode.S))
{
if (!doubleTap && doubleTapTime > Time.time && _lastKeyCode == KeyCode.S)
{
rb.velocity = new Vector2(rb.velocity.x, -1 * dropSpeed);
Debug.Log("dashing right");
}
else
{
doubleTapTime = Time.time + 0.5f;
}
_lastKeyCode = KeyCode.S;
}
}
void Move()
{
//changes movement relative to input
if (!isDashing)
{
if (isGrounded && Input.GetKey(KeyCode.S))
{
rb.velocity = new Vector2(rb.velocity.x * .999f, rb.velocity.y);
}
else if (moveInputX == 0 && isGrounded)
{
speed = moveSpeed;
rb.velocity = new Vector2(rb.velocity.x * .99f, rb.velocity.y);
}
else if (moveInputX == 0 && !isGrounded)
{
speed = moveSpeed;
}
else
{
rb.velocity = new Vector2(moveInputX * speed, moveInputY / 10 + rb.velocity.y);
}
}
//checks player velocity
rbxVel = rb.velocity.x;
//increases speed relative to input direction
if (moveInputX > 0 || moveInputX < 0)
{
speed += acceleration;
}
//caps speed
if (speed > maxSpeed)
{
speed = maxSpeed;
}
//caps min speed
if (speed < moveSpeed)
{
speed = moveSpeed;
}
}
void Dash()
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
isDashing = true;
if (isDashing && dashCoolCounter <= 0)
{
dashTime -= Time.deltaTime;
dashCoolCounter = dashCooldown;
rb.velocity = new Vector2(dashSpeed * direction, rb.velocity.y);
Debug.Log("Dash Started");
}
}
else
{
dashTime = maxDashTime;
isDashing = false;
Debug.Log("No Dash");
}
//resets dash cooldown
if (dashCoolCounter > 0)
{
dashCoolCounter -= Time.deltaTime;
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
}
When using the keys for movement (A, S) the dash doesn't function. Oddly enough the code is executing (I see my debug statement in console) but nothing physically changes.
When rewriting the code for the dash from: rb.velocity = new Vector2(dashSpeed * direction, rb.velocity.y) to: rb.velocity = dashspeed the dash will work without issue. The only downside to that is that the Y component of the RigidBody is being manipulated as well.
This has been an issue for days now, and I am just rewriting the post.
Any and all help is welcomed.
You're setting isDashing = false too soon. It gets set to false as soon as you let go of Shift which allows Move to execute its code and change your rigidbody's velocity back to normal move.
Didn't test this, but give it a shot and see if it works the way you want it to.
void Dash()
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
if (!isDashing && dashCoolCounter <= 0)
{
isDashing = true;
dashTime = 0;
dashCoolCounter = dashCooldown;
rb.velocity = new Vector2(dashSpeed * direction, rb.velocity.y);
Debug.Log("Dash Started");
}
else if(isDashing)
{
rb.velocity = new Vector2(dashSpeed * direction, rb.velocity.y);
dashTime += Time.deltaTime;
if(dashTime >= maxDashTime)
{
isDashing = false;
Debug.Log("No Dash");
}
}
}
// resets dash cooldown
if (dashCoolCounter > 0)
{
dashCoolCounter -= Time.deltaTime;
}
}

How to go back to script after starting Coroutine?

I currently have a script that allows the player to pick up an item and plays an animation. I have a coroutine to wait 1 second before locking the game object to the player's hand. My problem is that my code for dropping the item and throwing it no longer functions. Is there a workaround to solve this problem?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PickUp : MonoBehaviour
{
bool isgrounded = true;
public Animator animator;
public GameObject Player;
public Rigidbody rb;
public bool inrange;
public int number = 1;
public Transform theDest;
public float thrust = 1.0f;
public float upthrust = 1.0f;
void start()
{
rb = GetComponent<Rigidbody>();
inrange = false;
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.name == "Player")
{
inrange = true;
}
}
private void OnTriggerExit(Collider other)
{
inrange = false;
}
public void Update()
{
bool isPickUp = animator.GetBool("isPickUp");
bool pickuppressed = Input.GetKey("e");
if (isgrounded == true)
{
if (pickuppressed && !isPickUp && inrange==true)
{
animator.SetBool("isPickUp", true);
}
if (!pickuppressed && isPickUp || inrange == false)
{
animator.SetBool("isPickUp", false);
}
if (Input.GetKeyUp(KeyCode.E) && (number % 2) == 1 && inrange == true )
{
StartCoroutine(waiter());
number = number + 1;
}
else if (Input.GetKeyUp(KeyCode.E) && (number % 2) == 0 && inrange == true)
{
GetComponent<Rigidbody>().isKinematic = false;
GetComponent<BoxCollider>().enabled = true;
this.transform.parent = null;
GetComponent<Rigidbody>().useGravity = true;
number = number - 1;
}
else if (Input.GetKey(KeyCode.G) && (number % 2) == 0 && inrange == true)
{
GetComponent<Rigidbody>().isKinematic = false;
GetComponent<BoxCollider>().enabled = true;
this.transform.parent = null;
GetComponent<Rigidbody>().useGravity = true;
number = number - 1;
rb.AddForce(Player.transform.forward * thrust);
rb.AddForce(Player.transform.up * upthrust);
}
}
void OnCollisionEnter(Collision theCollision)
{
if (theCollision.gameObject.name == "floor")
{
isgrounded = true;
}
}
//consider when character is jumping .. it will exit collision.
void OnCollisionExit(Collision theCollision)
{
if (theCollision.gameObject.name == "floor")
{
isgrounded = false;
}
}
IEnumerator waiter()
{
yield return new WaitForSeconds(1);
GetComponent<BoxCollider>().enabled = false;
GetComponent<Rigidbody>().useGravity = false;
GetComponent<Rigidbody>().isKinematic = true;
this.transform.position = theDest.position;
this.transform.parent = GameObject.Find("Destination").transform;
}
}
}
Let me know if more information is needed (still new to stack overflow)
Forget about the coroutine and use Time.time to save the time of pickup to a class variable. Then add comparison to the other if branches such as Time.time > pickupTime + 1f.

Categories