using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TankScopeScript : MonoBehaviour
{
public float speed;
private float waitTime;
public float startWaitTime;
public Transform[] moveSpots;
private int randomSpot;
public Transform random;
void Start()
{
random = moveSpots[Random.Range(0, moveSpots.Length)];
}
// Update is called once per frame
void Update()
{
transform.position = Vector3.MoveTowards(transform.position, moveSpots[random].position, speed * Time.deltaTime);
if (Vector3.Distance(transform.position, moveSpots[random].position) < 0.2f)
{
if (waitTime <= 0)
{
random = moveSpots[Random.Range(0, moveSpots.Length)];
waitTime = startWaitTime;
transform.LookAt(random);
}
else
{
waitTime -= Time.deltaTime;
}
}
}
}
want to use transform.LookAt(randomSpot) but i cant...error with int to transform, help me please...
i tried to create public Transform random; and assign a value randomSpot, but, again error
Assets\Resources\Script2\TankScopeScript.cs(23,70): error CS0029: Cannot implicitly convert type 'UnityEngine.Transform' to 'int'
You are trying to get an element of an array using the random variable, but that is one of your points rather than an index. Instead of using moveSpots[random].position you should replace it with random.position.
So line 23 would become transform.position = Vector3.MoveTowards(transform.position, random.position, speed * Time.deltaTime); and line 25 would become if (Vector3.Distance(transform.position, random.position) < 0.2f).
Related
I'm trying to make it so that every time I kill an enemy, my player's speed increases by 1. I've been trying to do this but I don't really know what I'm doing. Can somebody help me?
Here is my player movement script
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float MovementSpeed = 5;
public float JumpForce = 5;
private Rigidbody2D _rigidbody;
private void Start()
{
_rigidbody = GetComponent<Rigidbody2D>();
}
private void Update()
{
//Movement
var movement = Input.GetAxis("Horizontal");
transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * MovementSpeed;
if (Input.GetButtonDown("Jump") && Mathf.Abs(_rigidbody.velocity.y) < 0.001f)
{
_rigidbody.AddForce(new Vector2(0, JumpForce), ForceMode2D.Impulse);
}
}
}
Here is my Enemy script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class enemyScript : MonoBehaviour
{
public int health = 100;
private static float speed;
private static float jump;
public void TakeDamage(int damage)
{
health -= damage;
if (health <= 0)
{
Die();
speed += 1.0f;
jump += 1.0f;
}
}
void Die()
{
Destroy(gameObject);
speed = GetComponent<PlayerMovement>().MovementSpeed;
jump = GetComponent<PlayerMovement>().JumpForce;
}
}
Sorry, my question didn't have all the details, the player is not gaining any speed. I tried using
GetComponent<PlayerMovement>().MovementSpeed += 1.0f;
GetComponent<PlayerMovement>().JumpForce += 1.0f;
and now I'm getting this error message
NullReferenceException: Object reference not set to an instance of an object
Sorry for the inconvenience
First of all it makes no sense to use GetComponent since the PlayerMovement is not attached to your enemy objects.
Then
speed = GetComponent<PlayerMovement>().MovementSpeed;
jump = GetComponent<PlayerMovement>().JumpForce
is also the wrong way round .. what use would it be to take the value from the player and store it in a field of the enemy?
If there is only one player anyway you could simply use FindObjectOfType and do
void Die()
{
Destroy(gameObject);
FindObjectOfType<PlayerMovement>().MovementSpeed += 1.0f;
FindObjectOfType<PlayerMovement>().JumpForce += 1.0f;
}
Or alternatively use a Singleton Pattern as actually even suggested by before mentioned docs like e.g.
public class PlayerMovement : MonoBehaviour
{
public static PlayerMovement Instance { get; private set;}
private void Awake ()
{
if(Instance && Instance!= this)
{
Destroy(gameObject);
return;
}
Instance = this;
}
...
}
and then simply do
void Die()
{
Destroy(gameObject);
PlayerMovement.Instance.MovementSpeed += 1.0f;
PlayerMovement.Instance.JumpForce += 1.0f;
}
I am assuming you want to increase the jumpforce and speed of your player when the player kills an enemy. Also, Could you please elaborate the question if you are getting any error or just the speed is not increasing?
Please find the inline response for the Enemy Script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class enemyScript : MonoBehaviour
{
public int health = 100;
private static float speed;//This is enemy speed variable that you have declared
private static float jump;//This is enemy jump variable that you have declared
public void TakeDamage(int damage)
{
health -= damage;
if (health <= 0)
{
Die();
//speed += 1.0f; Here you are increasing enemy speed and not playerspeed.
//jump += 1.0f; Same goes for jump.
}
}
void Die()
{
Destroy(gameObject);
//speed = GetComponent<PlayerMovement>().MovementSpeed; here you are assigning Player movement speed to enemy speed.
//jump = GetComponent<PlayerMovement>().JumpForce; here you are assigning Player movement jump to enemy jump.
//Instead try
GetComponent<PlayerMovement>().MovementSpeed += 1.0f;
GetComponent<PlayerMovement>().JumpForce += 1.0f;
}
}
Also you can use
Debug.Log(your movementspeed variable);
to check if the player speed is being increased or not.
Please check the code. Once the player moves the fixed distance once, he doesn't move again even when the space input is given.
How Do I make it such that I can keep moving the player after the player has been moved once?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovementPC : MonoBehaviour
{
[Header ("Move Settings")]
private Vector3 StartingPosition, EndingPosition;
public float moveDistance = 30f;
public float LerpTime = 1f;
private float CurrentLerpTime = 0;
public bool movePressed = false;
private void Start()
{
StartingPosition = transform.position;
EndingPosition = transform.position + Vector3.forward * moveDistance;
}
void Update()
{
if (Input.GetKeyDown("space"))
{
movePressed = true;
Debug.Log("dash pressed");
}
if (movePressed == true)
{
CurrentLerpTime += Time.unscaledDeltaTime;
if (CurrentLerpTime >= LerpTime)
{
CurrentLerpTime = LerpTime;
}
float LerpPercentage = CurrentLerpTime / LerpTime;
transform.position = Vector3.Lerp(StartingPosition, EndingPosition, LerpPercentage);
}
}
Any Help would be appreciated. Thanks for your time.
The issue is you are not resetting the variables that control the start/end positions of the movement. The Start() method is called when the object is added to the level, or Play is pressed and that is currently the only method that resets those values. Therefore if you want those values reset you need to determine when the movement has finished, something like:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovementPC : MonoBehaviour
{
[Header ("Move Settings")]
private Vector3 StartingPosition, EndingPosition;
public float moveDistance = 30f;
public float LerpTime = 1f;
private float CurrentLerpTime = 0;
private void Start()
{
ResetPositions();
}
void Update()
{
if (Input.GetKeyDown("space"))
{
CurrentLerpTime += Time.unscaledDeltaTime;
if (CurrentLerpTime >= LerpTime)
{
ResetPositions();
return;
}
float LerpPercentage = CurrentLerpTime / LerpTime;
transform.position = Vector3.Lerp(StartingPosition, EndingPosition, LerpPercentage);
}
}
void ResetPositions()
{
StartingPosition = transform.position;
EndingPosition = transform.position + Vector3.forward * moveDistance;
CurrentLerpTime = 0;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotateCamera : MonoBehaviour
{
public GameObject objectToSpin;
public float spinX;
public float spinY;
public float spinZ;
public bool randomSpin = false;
private void Start()
{
var rb = GetComponent<Rigidbody>();
rb.angularVelocity = Random.insideUnitSphere;
}
private void Update()
{
if (randomSpin == true)
{
objectToSpin.transform.Rotate(Random.Range(spinX, 360), Random.Range(spinY, 360), Random.Range(spinZ, 360));
}
else
{
objectToSpin.transform.Rotate(spinX, spinY, spinZ);
}
}
}
Now when changing the randomSpin flag to true it will spin random nonstop changing random angle on x y z each frame.
But I want it to spin random for 5 seconds after 5 seconds to change to random values the x y z and continue from last point and then after 5 seconds random angles and so on.
If you want a constant speed and just a random direction, You can randomly select an Axis to rotate around using Random.onUnitSphere and then rotate around it at a speed.
Here's a solution that uses a Coroutine. If you want to stop the Coroutine, you can use StopCoroutine("Spin") to stop the coroutine and start it up later with StartCoroutine("Spin"):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotateCamera : MonoBehaviour
{
public GameObject objectToSpin;
public Vector3 spinAxis;
public float timeToSpin = 5f;
public float spinSpeed = 20f;
public bool randomSpin = false;
private void Start()
{
var rb = GetComponent<Rigidbody>();
rb.angularVelocity = Random.insideUnitSphere;
StartCoroutine("Spin");
}
private void Update()
{
}
}
IEnumerator Spin()
{
float spinTimer;
while (true)
{
if (randomSpin == true)
{
spinAxis = Random.onUnitSphere;
}
spinTimer = timeToSpin;
while (spinTimer > 0f)
{
objectToSpin.transform.Rotate(spinAxis, Time.deltaTime * spinSpeed);
spinTimer -= Time.deltaTime;
yield return null;
}
}
}
For example have a simple timer using Time.deltaTime like e.g.
private float timer = 5;
private void Update()
{
if (randomSpin == true)
{
timer -= Time.deltaTime;
if(timer <= 0)
{
objectToSpin.transform.Rotate(Random.Range(spinX, 360), Random.Range(spinY, 360), Random.Range(spinZ, 360));
timer = 5;
}
}
else
{
objectToSpin.transform.Rotate(spinX, spinY, spinZ);
}
}
I don't know why, but I see to be getting thrown this error.. I followed a tutorial and haven't missed anything so far but now I have come to this.
The type or namespace name 'Score' could not be found (are you missing a using directive or an assembly reference?)
PlayerMotor.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class PlayerMotor : MonoBehaviour
{
private CharacterController controller;
private Vector3 moveVector;
private float speed = 10.0f;
private float verticalVelocity = 0.0f;
private float gravity = 12.0f;
private float animationDuration = 3.0f;
private bool isDead = false;
void Start () {
controller = GetComponent<CharacterController>();
}
void Update () {
if (isDead)
return;
if(Time.time < animationDuration)
{
controller.Move(Vector3.forward * speed * Time.deltaTime);
return;
}
moveVector = Vector3.zero;
if(controller.isGrounded)
{
verticalVelocity = -0.5f;
}
else
{
verticalVelocity -= gravity * Time.deltaTime;
}
// X - Left and Right
moveVector.x = Input.GetAxisRaw("Horizontal") * speed;
// Y - Up and Dow
moveVector.y = verticalVelocity;
// Z - Forward and Backward
moveVector.z = speed;
controller.Move (moveVector * Time.deltaTime);
}
public void SetSpeed(float modifier)
{
speed = 10.0f + modifier;
}
private void OnControllerColliderHit (ControllerColliderHit hit)
{
if (hit.point.z > transform.position.z + controller.radius)
Death();
}
private void Death()
{
isDead = true;
GetComponent<Score>().OnDeath();
}
}
Score.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Score : MonoBehaviour
{
private float score = 0.0f;
private int difficultyLevel = 1;
private int maxDifficultyLevel = 10;
private int scoreToNextLevel = 10;
private bool isDead = false;
public Text scoreText;
void Update () {
if (isDead)
return;
if (score >= scoreToNextLevel)
LevelUp();
score += Time.deltaTime * difficultyLevel;
scoreText.text = ((int)score).ToString ();
}
void LevelUp()
{
if (difficultyLevel == maxDifficultyLevel)
return;
scoreToNextLevel *= 2;
difficultyLevel++;
GetComponent<PlayerMotor>().SetSpeed (difficultyLevel);
Debug.Log (difficultyLevel);
}
public void OnDeath()
{
isDead = true;
}
}
I am guessing both the scripts you have mentioned here are not attached to the same game object.
A quick fix to this would be to create a variable for the score script in your PlayerMotor script and then drag the score script to the variable in the editor to set it.
or you could just
do
GameObject.Find("Player").GetComponent<Score>().OnDeath();
or maybe you destroy the gameobject of the player on death, in that case nothing will work.
I'm not evening joking, I closed everything, reopened it and it works.
I'm done
I am trying to make my enemy object turn and start moving towards my player object when the player comes within a certain vicinity.
For the turning I have been testing the transform.LookAt() function although it isn't returning the desired results as when the player is too close to the enemy object the enemy starts to tilt backwards and I only want my enemy to be able to rotate along the y axis, thanks in advance.
using UnityEngine;
using System.Collections;
public class EnemyController : MonoBehaviour {
public Transform visionPoint;
private PlayerController player;
public Transform Player;
public float visionAngle = 30f;
public float visionDistance = 10f;
public float moveSpeed = 2f;
public float chaseDistance = 3f;
private Vector3? lastKnownPlayerPosition;
// Use this for initialization
void Start () {
player = GameObject.FindObjectOfType<PlayerController> ();
}
// Update is called once per frame
void Update () {
// Not giving the desired results
transform.LookAt(Player);
}
void FixedUpdate () {
}
void Look () {
Vector3 deltaToPlayer = player.transform.position - visionPoint.position;
Vector3 directionToPlayer = deltaToPlayer.normalized;
float dot = Vector3.Dot (transform.forward, directionToPlayer);
if (dot < 0) {
return;
}
float distanceToPlayer = directionToPlayer.magnitude;
if (distanceToPlayer > visionDistance)
{
return;
}
float angle = Vector3.Angle (transform.forward, directionToPlayer);
if(angle > visionAngle)
{
return;
}
RaycastHit hit;
if(Physics.Raycast(transform.position, directionToPlayer, out hit, visionDistance))
{
if (hit.collider.gameObject == player.gameObject)
{
lastKnownPlayerPosition = player.transform.position;
}
}
}
}
change the look at target:
void Update () {
Vector3 lookAt = Player.position;
lookAt.y = transform.position.y;
transform.LookAt(lookAt);
}
this way the look at target will be on the same height as your object.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemyMovement : MonoBehaviour
{
public Transform Player;
public float MoveSpeed = 4;
int MaxDist = 10;
int MinDist = 5;
void Update()
{
transform.LookAt(Player);
if (Vector3.Distance(transform.position, Player.position) >= MinDist)
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
if (Vector3.Distance(transform.position, Player.position) <= MaxDist)
{
// Put what do you want to happen here
}
}
}
}