OnGUI is called just in first component - c#

I'm creating a game to learn about Unity watching a tutorial (this one) and my Player has two components: PlayerHealth and PlayerAttack. The both are working fine as well but the problem is when I tried to do something in a OnGUI of second component (PlayerAttack), the OnGUI in PlayerAttack is never called.
Is because PlayerAttack is added below PlayerHealth? Follow below the codes e some prints.
PlayerHealth.cs
using UnityEngine;
using System.Collections;
public class PlayerHealth : MonoBehaviour {
public int maxHealth = 100;
public int curHealth = 100;
public float healthBarLenght;
// Use this for initialization
void Start () {
healthBarLenght = Screen.width / 3;
}
// Update is called once per frame
void Update () {
AddjustCurrentHealth(0);
}
void OnGUI(){
GUI.Box(new Rect(10, 10, healthBarLenght, 20), curHealth + "/" + maxHealth);
}
public void AddjustCurrentHealth(int adj){
curHealth += adj;
curHealth = Mathf.Min(Mathf.Max(curHealth, 0), maxHealth);
maxHealth = Mathf.Max(maxHealth, 1);
healthBarLenght = ((float) Screen.width / 3) * (curHealth / (float) maxHealth);
}
}
PlayerAttack.cs
using UnityEngine;
using System.Collections;
public class PlayerAttack : MonoBehaviour {
public GameObject target;
public float attackTimer;
public float coolDown;
// Use this for initialization
void Start () {
attackTimer = 0;
coolDown = 2;
}
// Update is called once per frame
void Update () {
if(attackTimer > 0){
attackTimer -= Time.deltaTime;
} else {
attackTimer = 0;
}
if(Input.GetKeyUp(KeyCode.F) && attackTimer == 0){
attackTimer = coolDown;
Attack();
}
}
void onGUI(){
float loadPct = coolDown - attackTimer;
GUI.Box(new Rect(10, 30, loadPct, 10), loadPct + "%");
}
private void Attack(){
float distance = Vector3.Distance(target.transform.position, transform.position);
Vector3 dir = (target.transform.position - transform.position).normalized;
float direction = Vector3.Dot(dir, transform.forward);
Debug.Log(direction);
if(distance <= 2.5 && direction > 0.9)
{
EnemyHealth eh = (EnemyHealth) target.GetComponent("EnemyHealth");
eh.AddjustCurrentHealth(-1);
}
}
}

Your OnGUI method on PlayerAttack class is typed "onGUI", not "OnGUI" (capital O). Remember C# is case-sensitive.

Related

How can I make the animation match when the NPC walks left or right?

I have some NPCs that randomly walk within a range, however when I can't determine when they are walking left or right so the animation looks wrong.
I have a function called "Decrease" that warns inside the terminal when the object walks decreases or increases its position, but this function does not work as it should
So...
How can I make the animation match when the NPC walks left or right?
Here is my NPC configuration:
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NPCController : MonoBehaviour
{
private float waitTime;
private Animator _animator;
private SpriteRenderer _renderer;
public Transform moveSpot;
private bool _facingRight = true;
public float lastXVal;
public float speed;
public float startWaitTime;
public float minX;
public float maxX;
public float minY;
public float maxY;
void Awake()
{
_animator = GetComponent<Animator>();
_renderer = GetComponent<SpriteRenderer>();
}
void Start()
{
waitTime = startWaitTime;
moveSpot.position = new Vector2(Random.Range(minX, maxX), Random.Range(minY, maxY));
}
void Update()
{
transform.position = Vector2.MoveTowards(transform.position, moveSpot.position, speed * Time.deltaTime);
if (Vector2.Distance(transform.position, moveSpot.position) < 0.2f)
{
//Change animation state
if (waitTime <= 0)
{
_animator.SetBool("Walk", true);
moveSpot.position = new Vector2(Random.Range(minX, maxX), Random.Range(minY, maxY));
waitTime = startWaitTime;
}
else
{
_animator.SetBool("Walk", false);
_animator.SetBool("Idle", true);
waitTime -= Time.deltaTime;
}
}
}
public void Decrease()
{
if (transform.hasChanged)
{
if (transform.position.x < lastXVal)
{
//Update lastXVal
lastXVal = transform.position.x;
Debug.Log("Decreased!");
}
else if (transform.position.x > lastXVal)
{
//Update lastXVal
lastXVal = transform.position.x;
Debug.Log("Increased");
}
transform.hasChanged = false;
}
}
}
You can use dot product to calculate the direction of travel.
Vector2 moveDirection = (moveSpot.position - transform.position).normalized;
float dotValue = Vector2.Dot(Vector2.right, moveDirection)
// if dotValue is 1 then you are moving right and if dotValue is -1 you are moving left

Instantiating Custom Object in Unity MonoBehaviour Scripts

I'm trying to programm my own little game in Unity, I'm not new to programming but new to Unity and C#. The problem is that I wrote my own classes to handle the game map and I am trying to connect these classes to the MonoBehaviour Scripts in Unity.
I have a script called InputManager, which is supposed to handle the input via mouse and keyboard etc. and in this script I want to create an object of the class MapManager which has access to my tiles and stuff. The problem I'm getting is that I can't seem to create an instance of MapManager in InputManager, not with the common new MapManager() anyway. When I use this a NullPointer of some sort is created, I guess?
I do not get a compiling error but an error once the game is launched which is:
NullReferenceException: Object reference not set to an instance of an object
InputManager.Update () (at Assets/Scripts/InputManager.cs:55)
Thank you for your help!
!UPDATE!:
I tried using a workaround so that it does not matter if Start() or Update() is called first, meaning that I just instantiate MapManager in the first Update() call. However, when I run the program the error is still the same. My conclusion is that somehow my constructor is not working or the Monobehaviour script somehow does not allow using the standard constructor... Any ideas?
Here is my code:
InputManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class InputManager : MonoBehaviour
{
public int mapRightBorder = 10;
public int mapLeftBorder = -10;
public int mapTopBorder = 8;
public int mapBottomBorder = -4;
public double camSpeed = 0.2;
public double mouseSensitivity = 0.3;
public double scrollSensitivity = 2;
public double maxZoomIn = -3;
public double maxZoomOut = -12;
public Tilemap ground, overlays, buildings;
public Tilemap selected;
public AnimatedTile animatedTile;
private double detectionBorder;
private double leftRightCorrection;
private MapManager mapManager;
// Start is called before the first frame update
void Start()
{
detectionBorder = 50;
leftRightCorrection = 1.2;
mapManager = new MapManager();
mapManager.ground = ground;
mapManager.overlays = overlays;
mapManager.buildings = buildings;
mapManager.selected = selected;
mapManager.animatedTile = animatedTile;
Cursor.lockState = CursorLockMode.Confined;
}
// Update is called once per frame
void Update()
{
moveCam();
checkMouse();
mapManager.updateTilemaps();
}
private void moveCam()
{
double moveX = Camera.main.transform.position.x;
double moveY = Camera.main.transform.position.y;
double moveZ = Camera.main.transform.position.z;
double xPos = Input.mousePosition.x;
double yPos = Input.mousePosition.y;
double zDelta = Input.GetAxis("Mouse ScrollWheel");
if (Input.GetKey(KeyCode.LeftArrow))
{
moveX -= camSpeed * leftRightCorrection;
}
else if (xPos >= 0 && xPos < detectionBorder)
{
moveX -= camSpeed * mouseSensitivity * leftRightCorrection;
}
else if (Input.GetKey(KeyCode.RightArrow))
{
moveX += camSpeed * leftRightCorrection;
}
else if (xPos <= Screen.width && xPos > Screen.width - detectionBorder)
{
moveX += camSpeed * mouseSensitivity * leftRightCorrection;
}
if(moveX > mapRightBorder || moveX < mapLeftBorder)
{
moveX = Camera.main.transform.position.x;
}
if (Input.GetKey(KeyCode.DownArrow))
{
moveY -= camSpeed;
}
else if (yPos >= 0 && yPos < detectionBorder)
{
moveY -= camSpeed * mouseSensitivity;
}
else if (Input.GetKey(KeyCode.UpArrow))
{
moveY += camSpeed;
}
else if (yPos <= Screen.height && yPos > Screen.height - detectionBorder)
{
moveY += camSpeed * mouseSensitivity;
}
if(moveY > mapTopBorder || moveY < mapBottomBorder)
{
moveY = Camera.main.transform.position.y;
}
if (!(moveZ + zDelta * scrollSensitivity > maxZoomIn || moveZ + zDelta * scrollSensitivity < maxZoomOut))
{
moveZ += zDelta * scrollSensitivity;
}
Vector3 newPos = new Vector3((float)moveX, (float)moveY, (float) moveZ);
Camera.main.transform.position = newPos;
}
private void checkMouse()
{
if (Input.GetMouseButtonDown(0))
{
mapManager.selectTile(Input.mousePosition);
}
}
}
MapManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class MapManager
{
public int mapWidth = 16;
public int mapHeight = 16;
public Tilemap ground, overlays, buildings;
public Tilemap selected;
public AnimatedTile animatedTile;
private Vector3Int currentlySelected;
private OwnTilemap tilemap;
public MapManager()
{
tilemap = new OwnTilemap(mapWidth, mapHeight, ground, overlays, buildings);
currentlySelected = new Vector3Int(-1, -1, 0);
}
private Vector3Int mouseToTilemap(Vector3 mousePosition)
{
Ray ray = Camera.main.ScreenPointToRay(mousePosition);
// create a plane at 0,0,0 whose normal points to +Y:
Plane hPlane = new Plane(Vector3.forward, Vector3.zero);
// Plane.Raycast stores the distance from ray.origin to the hit point in this variable:
float enter = 0.0f;
if (hPlane.Raycast(ray, out enter))
{
//Get the point that is clicked
Vector3 hitPoint = ray.GetPoint(enter);
Vector3Int cell = ground.WorldToCell(hitPoint);
return cell;
}
return new Vector3Int(-1, -1, 0);
}
private bool isInBorders(Vector3Int p)
{
if (p.z != 0) return false;
if (p.x < 0 || p.x >= mapWidth) return false;
if (p.y < 0 || p.y >= mapHeight) return false;
return true;
}
public void updateTilemaps()
{
tilemap.updateTilemaps();
}
public void previewBuilding()
{
}
public void selectTile(Vector3 mousePosition)
{
if(currentlySelected != new Vector3Int(-1, -1, 0))
{
selected.SetTile(currentlySelected, null);
}
if (isInBorders(mouseToTilemap(mousePosition)))
{
selected.SetTile(mouseToTilemap(mousePosition), animatedTile);
currentlySelected = mouseToTilemap(mousePosition);
}
}
}

How do I assign a new transform.position for a GameObject that's triggered by an OnTriggerEnter in Unity?

I have code in my PlayerScript that, on collision with the floor game object (which I've tagged with "FloorTag"), decrements a variable called "Lives." Lives is decrementing, so I know the collision is registering (and everything is tagged correctly). However, I also want the Player game object's position to be reset to a specific Vector3 I've declared when it collides with the floor. For some reason, though, it's not doing this. Where have I gone wrong?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerScript : MonoBehaviour
{
public int Lives;
public Text LivesText;
public int Points;
public Text PointsText;
public Text GameOverText;
public CharacterController CharController;
public float moveSpeed = 9;
public float rotSpeed = 85;
float yVelocity = 0;
public float jumpForce = 2.5f;
public float gravityModifier = 0.025f;
bool prevIsGrounded;
Vector3 StartingPlatformCoords = new Vector3 (38, 16, 38);
// Start is called before the first frame update
void Start()
{
Lives = 8;
SetLivesText();
Points = 0;
SetPointsText();
prevIsGrounded = CharController.isGrounded;
//CharController = gameObject.GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
// L-R Forward-Back Motion
float hAxis = Input.GetAxis("Horizontal");
float vAxis = Input.GetAxis("Vertical");
transform.Rotate(0, rotSpeed * Time.deltaTime * hAxis, 0);
Vector3 amountToMove = transform.forward * moveSpeed * Time.deltaTime * vAxis;
// Jump Motion
if (CharController.isGrounded)
{
if (!prevIsGrounded && CharController.isGrounded)
{
yVelocity = 0;
}
if (Input.GetKeyDown(KeyCode.Space))
{
yVelocity = jumpForce;
}
}
else
{
if (Input.GetKeyUp(KeyCode.Space))
{
yVelocity = 0;
}
yVelocity += Physics.gravity.y * gravityModifier;
}
amountToMove.y = yVelocity;
// Modify the y-value within this Vector3 (which contains an x, y, z, and some utility functions like distance etc.) manually
// Final Motion
CharController.Move(amountToMove);
// Update
prevIsGrounded = CharController.isGrounded;
// Camera
Vector3 camPos = transform.position + transform.forward * -10 + Vector3.up * 3;
Camera.main.transform.position = camPos;
Camera.main.transform.LookAt(transform);
//if (Input.GetKeyDown(KeyCode.Space))
//{
//yVelocity = jumpForce;
//}
//yVelocity += Physics.gravity.y * gravityModifier;
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("FloorTag"))
{
transform.position = StartingPlatformCoords;
Lives -= 1;
SetLivesText();
Debug.Log(transform.position);
}
if (other.gameObject.CompareTag("CellTag"))
{
Points += 1;
SetPointsText();
}
}
void SetLivesText()
{
LivesText.text = "Lives: " + Lives.ToString();
if (Lives <= 0)
{
GameOverText.text = "Game Over";
}
}
void SetPointsText()
{
PointsText.text = "Score: " + Points.ToString();
}
}
CharacterController can override changes made to transform.position. Simplest workaround is to disable it, then re-enable it after directly modifying transform.position:
public CharacterController CharController;
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("FloorTag"))
{
CharController.enabled = false;
transform.position = StartingPlatformCoords;
CharController.enabled = true;
Lives -= 1;
SetLivesText();
Debug.Log(transform.position);
}
if (other.gameObject.CompareTag("CellTag"))
{
Points += 1;
SetPointsText();
}
}

Why isn't the AI following the player?

So I have written some code and everything works in it besides the AI following the player. I don't know what I did wrong so any help would be gladly appreciated!
public class SharkAI : MonoBehaviour
{
public float speed;
public Transform patrolPoints;
private float waitTime;
public float startWaitTime;
public float minX;
public float maxX;
public float minY;
public float maxY;
public float oldPosition;
public float newPosition;
private SpriteRenderer fishes;
public float eyeSightOfFish;
public float disToPlayer;
private Transform player;
// Start is called before the first frame update
void Start()
{
waitTime = startWaitTime;
patrolPoints.position = new Vector2(Random.Range(minX, maxX), Random.Range(minY, maxY));
fishes = GetComponent<SpriteRenderer>();
}
// Update is called once per frame
void Update()
{
player = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
oldPosition = transform.position.x;
newPosition = patrolPoints.position.x;
Debug.Log("Player distance " + disToPlayer);
//distToPatrolPoint = Vector3.Distance(transform.position, patrolPoints[whichPoint].transform.position);
disToPlayer = Vector2.Distance(transform.position, player.transform.position);
transform.position = Vector2.MoveTowards(transform.position, patrolPoints.position, speed * Time.deltaTime);
if (newPosition > oldPosition)
{
fishes.flipX = true;
}
else { fishes.flipX = false; }
if(disToPlayer <= eyeSightOfFish)
{
transform.position = Vector2.MoveTowards(transform.position, player.position, speed * Time.deltaTime);
}
else if (Vector2.Distance(transform.position, patrolPoints.position) <= 0.2f)
{
if (waitTime <= 0)
{
patrolPoints.position = new Vector2(Random.Range(minX, maxX), Random.Range(minY, maxY));
waitTime = startWaitTime;
}
else
{
waitTime -= Time.deltaTime;
}
}
}
}
so im not sure where this is wrong and ive tried a few things but I can't seem to make the ai follow the player.

I'm trying to display text with TextMeshPro on Unity, got the code running, with no error

I'm having difficulty changing text, on unity3d using TextmeshPro.
I'm new to coding and Unity, so I really don't know what to do.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PlayerController : MonoBehaviour
{
public float speed = 1.0f;
private int soldAmount;
private int currentAmount;
Rigidbody2D rigidbody2d;
TextMeshProUGUI graveValue;
TextMeshProUGUI scoreValue;
// Start is called before the first frame update
void Start()
{
scoreValue = GameObject.Find("Score").GetComponent<TextMeshProUGUI>();
graveValue = GameObject.Find("OrganTruth").GetComponent<TextMeshProUGUI>();
rigidbody2d = GetComponent<Rigidbody2D>();
currentAmount = 0;
soldAmount = 0;
}
// Update is called once per frame
void Update()
{
float Horizontal = Input.GetAxis("Horizontal");
float Vertical = Input.GetAxis("Vertical");
Vector2 position = rigidbody2d.position;
position.x = position.x + speed * Horizontal;
position.y = position.y + speed * Vertical;
rigidbody2d.position = position;
void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Graveyard")
{
while(currentAmount < 1)
{
currentAmount = currentAmount + 1;
graveValue.SetText(currentAmount.ToString());
}
}
if(collision.gameObject.tag == "OrganBuyer")
{
while(currentAmount == 1)
{
soldAmount = soldAmount + 1;
scoreValue.SetText(soldAmount.ToString());
}
}
}
}
}
It's supposed to change the text that organTruth and Score display, the soldAmount should be displayed after increasing by 1, and the organTruth should be a 1 after a collision.

Categories

Resources