I feel like my code should be really simple for me to understand, but I keep coming up with the same problem.
float contactWithPlayer = 1;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SheildMovement : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
sizeRandomised = Random.Range(playerModSize, playerModSize);
transform.localScale = new Vector3(sizeRandomised, sizeRandomised, sizeRandomised);
sideDrift = Random.Range(playerModSideDrift * -1 - 1, playerModSideDrift + 1);
downSpeed = Random.Range(playerModDownSpeed, playerModDownSpeed + 2);
}
//Global Variables
public int playerModSideDrift;
public int playerModDownSpeed;
public float playerModSize;
float sizeRandomised;
float sideDrift;
float downSpeed;
float contactWithPlayer = 1;
// Update is called once per frame
void Update()
{
Debug.Log(contactWithPlayer);
Vector3 cloneStats = new Vector3(sideDrift * .01f, -downSpeed * .01f, 0);
transform.position += cloneStats;
if (transform.position.y < -10)
{
Destroy(gameObject);
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Player")
{
contactWithPlayer = 2;
Destroy(gameObject);
}
}
}
The problem is: I am trying to get the update method to print out contact with Player = 2, but it keeps saying 1.
Related
I am currently learning C# as I'm studying a Games Design Course at University. I am currently implementing a system where: when the time reaches 0, the game pauses and ends. This works :).
However, at first I tried implementing the code into another script - but doesn't work on that script. This has puzzled me. Here is the code (that works):
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Health : MonoBehaviour
{
private Text TimeText;
public float HealthTimer;
public bool TimeIsRunning;
public GameObject CanvasEnd;
void Start()
{
TimeText = GameObject.Find("Timer").GetComponent<Text>();
TimeIsRunning = true;
CanvasEnd.SetActive(false);
}
void Update()
{
TimeText.text = HealthTimer.ToString("0");
if (TimeIsRunning == true)
{
if (HealthTimer > 0)
{
HealthTimer -= 1 * Time.deltaTime;
}
else
{
Time.timeScale = 0;
CanvasEnd.SetActive(true);
}
if(HealthTimer == 0)
{
TimeIsRunning = false;
HealthTimer = 0;
}
}
This script is directly attached to the timer. But I don't understand why it doesn't work when I implement it into another script (that already controls other game aspects). There were no errors, and everything was declared properly.
The exact same code was put into this script (in void update) and didn't work:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public GameObject Player;
public GameObject PlayerTracker;
public GameObject BlueBottle;
public GameObject GreenBottle;
public GameObject RedBottle;
public GameObject ChestCanvas;
public float Score;
public float ChestScoreK = 0;
private Text HT;
private Text HC;
private Text Port;
private Text TimeText;
float speed = 4;
float rotSpeed = 80;
float rot = 0f;
float gravity = 8;
// Variables counting Blue, Red and Green bottles
public int BBCounter = 0;
public int RBCounter = 0;
public int GBCounter = 0;
public int CCounter = 0;
Vector3 moveDir = Vector3.zero;
CharacterController controller;
Animator anim;
void Start()
{
controller = GetComponent<CharacterController>();
anim = GetComponent<Animator>();
ChestCanvas.SetActive(false);
TimeText = GameObject.Find("Timer").GetComponent<Text>();
}
void Update()
{
//Script was implemented here
if (controller.isGrounded)
{
if (Input.GetKey(KeyCode.W))
{
anim.SetInteger("condition", 1);
moveDir = new Vector3(0, 0, 1);
moveDir *= speed;
moveDir = transform.TransformDirection (moveDir);
}
if (Input.GetKeyUp(KeyCode.W))
{
anim.SetInteger("condition", 0);
moveDir = new Vector3(0, 0, 0);
}
}
rot += Input.GetAxis("Horizontal") * rotSpeed * Time.deltaTime;
transform.eulerAngles = new Vector3(0, rot, 0);
moveDir.y -= gravity * Time.deltaTime;
controller.Move(moveDir * Time.deltaTime);
}
private void FixedUpdate()
{
PlayerTracker.transform.position = Player.transform.position;
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "BlueBottle")
{
Debug.Log("BLUE");
BBCounter = BBCounter + 1;
GameObject MasterScriptBlue = GameObject.Find("GameMaster");
MasterScriptBlue.GetComponent<GameMasterScript>();
MasterScriptBlue.GetComponent<GameMasterScript>().BlueBottleCounter = BBCounter;
}
if (other.gameObject.tag == "RedBottle")
{
Debug.Log("RED");
RBCounter = RBCounter + 1;
GameObject MasterScriptRed = GameObject.Find("GameMaster");
MasterScriptRed.GetComponent<GameMasterScript>();
MasterScriptRed.GetComponent<GameMasterScript>().RedBottleCounter = RBCounter;
}
if (other.gameObject.tag == "GreenBottle")
{
Debug.Log("GREEN");
GBCounter = GBCounter + 1;
GameObject MasterScriptGreen = GameObject.Find("GameMaster");
MasterScriptGreen.GetComponent<GameMasterScript>();
MasterScriptGreen.GetComponent<GameMasterScript>().GreenBottleCounter = GBCounter;
}
if(other.gameObject.tag == "CityCollider")
{
GameObject HuntingCity = GameObject.Find("HC");
Destroy(HuntingCity);
ScoringSystem.theScore += 100;
Destroy(other.gameObject);
Debug.Log("Destroyed");
}
if(other.gameObject.tag == "TownCollider")
{
GameObject HuntingTown = GameObject.Find("HT");
Destroy(HuntingTown);
ScoringSystem.theScore += 100;
Destroy(other.gameObject);
Debug.Log("Destroyed");
Debug.Log("Destroyed");
}
if(other.gameObject.tag == "PortCollider")
{
GameObject Port = GameObject.Find("Port");
Destroy(Port);
ScoringSystem.theScore += 100;
Destroy(other.gameObject);
Debug.Log("Destroyed");
}
if(other.gameObject.tag == "Chest")
{
Time.timeScale = 0;
ChestCanvas.SetActive(true);
ChestScoreK += 1;
GameObject MasterScriptChest = GameObject.Find("GameMaster");
MasterScriptChest.GetComponent<GameMasterScript>().ChestScore += ChestScoreK;
Destroy(other.gameObject);
GameObject HealthScript = GameObject.Find("Timer");
HealthScript.GetComponent<Health>().TimeIsRunning = false;
}
}
}
What can I try next?
It's hard to understand the problem from your question, but if you are looking for potential problems in your script then it looks like you are comparing a float to zero here:
if(HealthTimer == 0)
{
TimeIsRunning = false;
HealthTimer = 0;
}
So it is possible that HealthTimer is never exactly zero.
You probbaly want if (HealthTimer <= 0f) instead, or to move that block into the else block of your preceding if statement.
Other differences with the second script are:
the second script is not setting TimeIsRunning = true; in the Start() method,
other methods set Time.timeScale = 0; in the second script (not sure what impact this has, but may be relevant).
Do you have the same 'using' tags at the top of your scripts? The 'text' class only exists in UnityEngine.UI, and not UnityEngine.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TargetMove : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.transform.position = RandomVector(0.1f, 0.5f);
}
private Vector3 RandomVector(float min, float max)
{
var x = Random.Range(min, max);
var y = Random.Range(min, max);
var z = Random.Range(min, max);
return new Vector3(transform.position.x + x, transform.position.y + y, transform.position.z);
}
}
I want it to move in small area randomly between 0.1 and 0.5 but since I did + x and + y it keep changing position and move far far nonstop.
return new Vector3(transform.position.x + x, transform.position.y + y, transform.position.z);
What should I do instead transform.position.x + x and transform.position.x + y ?
This is what I wanted :
The script is attached to a cube.
Another script is attached to the sci-fi drone I have that all is do is making the drone LookAt the cube.
That's it this create a lost control effect of the sci-fi drone shooting out of control.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TargetMove : MonoBehaviour
{
[SerializeField] private List<Vector3> waypoints = new List<Vector3>(); // Hom many items you want, will show in Inspector
public float speed;
private int current = 0;
private float WPradius = 1;
private void Start()
{
GetRandom();
}
private void Update()
{
MoveBetweenWaypoints();
}
private void GetRandom()
{
for (int i = 0; i < 30; i++)
{
waypoints.Add(new Vector3(Random.Range(transform.position.x, transform.position.x + 3f),
Random.Range(transform.position.y, transform.position.y + 3f),
transform.position.z));
}
}
private void MoveBetweenWaypoints()
{
if(Vector3.Distance(waypoints[current], transform.position) < WPradius)
{
current = Random.Range(0, waypoints.Count);
if(current >= waypoints.Count)
{
current = 0;
}
}
transform.position = Vector3.MoveTowards(transform.position, waypoints[current], Time.deltaTime * speed);
}
}
The problem is with the time delta.time function. It runs even after time Left variable crosses the value 0. I am an absolute newbie to coding so please help me.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
private Rigidbody rb;
public float speed = 1;
private int count;
//Text UI variables
public Text countText;
public Text winText;
public Text Timer;
private bool outOfTime = false;
public float totalTime = 15.00f;
private float timeLeft;
void Start()
{
rb = GetComponent<Rigidbody>();
count = 0;
SetTextUpdate();
winText.text = "";
timeLeft = totalTime;
// time left was declared as total time
}
void Update()
{
}
void FixedUpdate()
{
if (timeLeft < 0)
{
winText.text = "Oops, you lost";
outOfTime = true;
}
else
{
timeLeft = timeLeft - Time.deltaTime;
}
// the time left still continues to reduce even after reaching 0.
Timer.text = timeLeft.ToString();
float movementHorizontal = Input.GetAxis("Horizontal");
float movementVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(movementHorizontal, 0.0f, movementVertical);
rb.AddForce(movement * speed);
timeLeft -= Time.deltaTime;
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Pick Up"))
{
other.gameObject.SetActive(false);
count = count + 1;
SetTextUpdate();
}
}
void SetTextUpdate()
{
countText.text = "Count: " + count.ToString();
if (count == 10 && outOfTime == false)
{
winText.text = ("You win");
}
}
}
I am a complete newbie to coding so I hope to get help soon. It's just a simple 'Roll a Ball' game that I tried to modify with my given experience.
In FixedUpdate you are continuing to decrement the time and updating the display, even after time has run out. Try this:
void FixedUpdate()
{
if (timeLeft < 0)
{
Timer.text = timeLeft.ToString();
winText.text = "Oops, you lost";
outOfTime = true;
}
else
{
timeLeft = timeLeft - Time.deltaTime;
Timer.text = timeLeft.ToString();
}
// assume you want physics to continue after time is up
float movementHorizontal = Input.GetAxis("Horizontal");
float movementVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(movementHorizontal, 0.0f, movementVertical);
rb.AddForce(movement * speed);
// don't need this line timeLeft -= Time.deltaTime;
}
The first script is just making the camera to move over the terrain this script i'm not changing anything. The second script is PatrolData with that i feed the first script with data. The last script is the LookAt that should rotate the camera just a bit before moving to the next target(waypoint).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FlyToOverTerrain : MonoBehaviour
{
public Transform target;
public float desiredHeight = 10f;
public float flightSmoothTime = 10f;
public float maxFlightspeed = 10f;
public float flightAcceleration = 1f;
public float levelingSmoothTime = 0.5f;
public float maxLevelingSpeed = 10000f;
public float levelingAcceleration = 2f;
private Vector3 flightVelocity = Vector3.zero;
private float heightVelocity = 0f;
private void LateUpdate()
{
Vector3 position = transform.position;
float currentHeight = position.y;
if ((bool)target && flightAcceleration > float.Epsilon)
{
position = Vector3.SmoothDamp(position, target.position, ref flightVelocity, flightSmoothTime / flightAcceleration, maxFlightspeed, flightAcceleration * Time.deltaTime);
}
if (levelingAcceleration > float.Epsilon)
{
float targetHeight = Terrain.activeTerrain.SampleHeight(position) + desiredHeight;
position.y = Mathf.SmoothDamp(currentHeight, targetHeight, ref heightVelocity, levelingSmoothTime / levelingAcceleration, maxLevelingSpeed, levelingAcceleration * Time.deltaTime);
}
transform.position = position;
}
}
Then the data script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class PatrolData
{
public Transform target = null;
public float minDistance = 5f;
public float lingerDuration = 5f;
public float desiredHeight = 10f;
public float flightSmoothTime = 10f;
public float maxFlightspeed = 10f;
public float flightAcceleration = 1f;
public float levelingSmoothTime = 0.5f;
public float maxLevelingSpeed = 10000f;
public float levelingAcceleration = 2f;
}
public class PatrolOverTerrain : MonoBehaviour
{
public FlyToOverTerrain flyOverTerrain;
public enum PatrolMode { Clamp, Wrap, PingPong };
public PatrolData[] patrolPoints;
public PatrolMode mode = PatrolMode.Wrap;
private int iterator = 0;
private int index = 0;
private float lingerDuration = 0f;
public Vector3 distanceFromTarget;
private void OnEnable()
{
if (patrolPoints.Length > 0)
{
lingerDuration = patrolPoints[index].lingerDuration;
}
}
private void Update()
{
int length = patrolPoints.Length;
if (!flyOverTerrain) return;
if (patrolPoints.Length < 1) return;
if (index < 0) return;
var patrol = patrolPoints[index];
if (lingerDuration <= 0)
{
iterator++;
switch (mode)
{
case PatrolMode.Clamp:
index = (iterator >= length) ? -1 : iterator;
break;
case PatrolMode.Wrap:
iterator = Modulus(iterator, length);
index = iterator;
break;
case PatrolMode.PingPong:
iterator = Modulus(iterator, length * 2);
index = length - Mathf.Abs(length - iterator);
break;
}
if (index < 0) return;
patrol = patrolPoints[index];
flyOverTerrain.target = patrol.target;
flyOverTerrain.desiredHeight = patrol.desiredHeight;
flyOverTerrain.flightSmoothTime = patrol.flightSmoothTime;
flyOverTerrain.maxFlightspeed = patrol.maxFlightspeed;
flyOverTerrain.flightAcceleration = patrol.flightAcceleration;
flyOverTerrain.levelingSmoothTime = patrol.levelingSmoothTime;
flyOverTerrain.maxLevelingSpeed = patrol.maxLevelingSpeed;
flyOverTerrain.levelingAcceleration = patrol.levelingAcceleration;
lingerDuration = patrolPoints[index].lingerDuration;
}
Vector3 targetOffset = Vector3.zero;
if ((bool)patrol.target)
{
targetOffset = transform.position - patrol.target.position;
}
float sqrDistance = patrol.minDistance * patrol.minDistance;
if (targetOffset.sqrMagnitude <= sqrDistance)
{
flyOverTerrain.target = null;
lingerDuration -= Time.deltaTime;
}
else
{
flyOverTerrain.target = patrol.target;
}
distanceFromTarget = transform.position - patrol.target.position;
}
private int Modulus(int baseNumber, int modulus)
{
return (modulus == 0) ? baseNumber : baseNumber - modulus * (int)Mathf.Floor(baseNumber / (float)modulus);
}
}
And the lookat script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookAtCamera : MonoBehaviour {
//values that will be set in the Inspector
public Transform target;
public float RotationSpeed;
//values for internal use
private Quaternion _lookRotation;
private Vector3 _direction;
// Update is called once per frame
void Update()
{
//find the vector pointing from our position to the target
_direction = (target.position - transform.position).normalized;
//create the rotation we need to be in to look at the target
_lookRotation = Quaternion.LookRotation(_direction);
//rotate us over time according to speed until we are in the required rotation
transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, Time.deltaTime * RotationSpeed);
}
}
All scripts are attached to the Main Camera. Until now it was working fine the camera moved between the targets. Now what i want to do is when the camera stop near each target just a bit before the camera start moving to the next target make a rotation to be facing to the target it's going to be moving to.
The problem is i don't know how to make it wait and how much and when to start the rotation in the LookAtCamera script.
Now what it does when running the game it's start rotating right away to the next target(in inspector i dragged for testing the second target).
My problem is how to work with the LookAtCamera script.
Found how to do it.
First in the LookAtCamera script that attached it to the Main Camera i also check that there is a target existing in the Update function:
if (target)
so the Update function:
void Update()
{
//find the vector pointing from our position to the target
if (target)
_direction = (target.position - transform.position).normalized;
//create the rotation we need to be in to look at the target
_lookRotation = Quaternion.LookRotation(_direction);
//rotate us over time according to speed until we are in the required rotation
transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, Time.deltaTime * RotationSpeed);
}
Then in the script PatrolData:
The script PatrolData can be attached to any gameobject in this case i attached it to the Main Camera too.
In the top of FlyToVerTerrain i added:
public LookAtCamera lookAtCamera;
Then in the Update function:
lookAtCamera.target = patrol.target;
lookAtCamera.RotationSpeed = 3;
Then at this part:
if (targetOffset.sqrMagnitude <= sqrDistance)
{
flyOverTerrain.target = null;
lookAtCamera.target = null;
lingerDuration -= Time.deltaTime;
}
else
{
flyOverTerrain.target = patrol.target;
lookAtCamera.target = patrol.target;
}
In the end all the 3 scripts make that the camera will move to each waypoint(target), The camera will rotate and will face to the next waypoint before moving to the next waypoint.
Working perfect.
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(); }.