I'm making 2D Game like Pac-Man. Nevertheless, I have some issues to create a scoring system.
I want to update score whenever my Pacman eat coin(a.k.a pacdot)
I made C# script called 'ScoreManager'
Here is code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScoreManager : MonoBehaviour {
static int score = 0;
public static void setScore(int value)
{
score += value;
}
public static int getScore()
{
return score;
}
void OnGUI ()
{
GUILayout.Label("Score: " + score.ToString());
}
}
This code is working well when I play my game in Unity engine
But, I don't know how to set up ScoreValue in Pacdot scripts.
Here is Pacdot Code
using UnityEngine;
using System.Collections;
public class Pacdot : MonoBehaviour {
public int score = 10;
void OnTriggerEnter2D(Collider2D co) {
if (co.name == "pacman")
{
Destroy(gameObject);
}
}
}
Also, I added C# Script ( Pacmanbehaviour )
using UnityEngine;
using System.Collections;
public class PacmanMove : MonoBehaviour {
public float speed = 0.4f;
Vector2 dest = Vector2.zero;
void Start() {
dest = transform.position;
}
void FixedUpdate() {
// Move closer to Destination
Vector2 p = Vector2.MoveTowards(transform.position, dest, speed);
GetComponent<Rigidbody2D>().MovePosition(p);
// Check for Input if not moving
if ((Vector2)transform.position == dest) {
if (Input.GetKey(KeyCode.UpArrow) && valid(Vector2.up))
dest = (Vector2)transform.position + Vector2.up;
if (Input.GetKey(KeyCode.RightArrow) && valid(Vector2.right))
dest = (Vector2)transform.position + Vector2.right;
if (Input.GetKey(KeyCode.DownArrow) && valid(-Vector2.up))
dest = (Vector2)transform.position - Vector2.up;
if (Input.GetKey(KeyCode.LeftArrow) && valid(-Vector2.right))
dest = (Vector2)transform.position - Vector2.right;
}
// Animation Parameters
Vector2 dir = dest - (Vector2)transform.position;
GetComponent<Animator>().SetFloat("DirX", dir.x);
GetComponent<Animator>().SetFloat("DirY", dir.y);
}
bool valid(Vector2 dir) {
// Cast Line from 'next to Pac-Man' to 'Pac-Man'
Vector2 pos = transform.position;
RaycastHit2D hit = Physics2D.Linecast(pos + dir, pos);
return (hit.collider == GetComponent<Collider2D>());
}
}
ScoreManager script needs to live as a game object, or as a component in a game object. Then you can add it as a field in your Pacdot class.
It'll be something like this below, but finding the specific game object the script is attached to will depend on how you have it designed (the "find by tag" approach won't work unless you have a game object with ScoreManager attached, with that tag).
using UnityEngine;
using System.Collections;
public class Pacdot : MonoBehaviour {
public int score = 10;
private ScoreManager _score = GameObject.findGameObjectWithTag("scoreKeeper").GetComponent<ScoreManager>();
void OnTriggerEnter2D(Collider2D co) {
if (co.name == "pacman")
{
_score.SetScore(score);
Destroy(gameObject);
}
}
}
I would also look at the answer #derHugo linked to--a lot of ways to accomplish this, depending on your needs/design.
Related
I have been working on a unity project where the player controls a ship. I was following along with a tutorial and have made an input script and a movement script that are tied together with unity's event system. As far as I can tell my script and the script in the tutorial are the same, but the tutorial script functions and mine doesn't.
Script to get player input
using UnityEngine;
using System.Collections;
using System;
using UnityEngine.Events;
public class PlayerInput : MonoBehaviour
{
public UnityEvent<Vector2> OnBoatMovement = new UnityEvent<Vector2>();
public UnityEvent OnShoot = new UnityEvent();
void Update()
{
BoatMovement();
Shoot();
}
private void Shoot()
{
if(Input.GetKey(KeyCode.F))
{
OnShoot?.Invoke();
}
}
private void BoatMovement()
{
Vector2 movementVector = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
OnBoatMovement?.Invoke(movementVector.normalized);
}
}
Script to move player
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class Movement : MonoBehaviour
{
public Rigidbody2D rb2d;
private Vector2 movementVector;
public float maxspeed = 10;
public float rotatespeed = 50;
private void Awake()
{
rb2d = GetComponent<Rigidbody2D>();
}
public void HandleShooting()
{
Debug.Log("Shooting");
}
public void Handlemovement(Vector2 movementVector)
{
this.movementVector = movementVector;
}
private void FixedUpdate()
{
rb2d.velocity = (Vector2)transform.up * movementVector.y * maxspeed * Time.deltaTime;
rb2d.MoveRotation(transform.rotation * Quaternion.Euler(0, 0, -movementVector.x * rotatespeed * Time.fixedDeltaTime));
}
}
Any help would be appreciated!
You need to attach your Handlers (HandleShooting and Handlemovement) to corresponding events. Easiest way would be to make events static in PlayerInput
public static UnityEvent<Vector2> OnBoatMovement = new UnityEvent<Vector2>();
public static UnityEvent OnShoot = new UnityEvent();
and attach corresponding handlers to them in Movement.Awake
private void Awake(){
rb2d = GetComponent<Rigidbody2D>();
PlayerInput.OnBoatMovement += Handlemovement;
PlayerInput.OnShoot += HandleShooting;
}
Also in PlayerInput.BoatMovement you should probably check
if(movementVector.sqrMagnitude > 0){
OnBoatMovement?.Invoke(movementVector.normalized);
}
Or else random shit may happen when trying to normalize Vector with magnitude 0 (I compare sqr magnitude to aviod calculating root which is never desired)
I'm making a unity shooter. The task was to remove hp from each enemy in its own way.
My code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class monster_animation : MonoBehaviour
{
public GameObject player;
public float dist;
NavMeshAgent nav;
public float Radius = 40f;
public static int health = 100;
// Start is called before the first frame update
void Start()
{
nav = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update()
{
if (GameObject.Find("HitEffect(Clone)") != null)
{
health -= 25;
Destroy(GameObject.Find("HitEffect(Clone)"));
}
dist = Vector3.Distance(player.transform.position, transform.position);
if(dist <= Radius)
{
if (dist <= 4)
{
nav.enabled = false;
if (health <= 0)
{
nav.enabled = false;
gameObject.GetComponent<Animator>().SetTrigger("dead");
}
else
{
gameObject.GetComponent<Animator>().SetTrigger("attack");
}
}
else
{
if (health <= 0)
{
nav.enabled = false;
gameObject.GetComponent<Animator>().SetTrigger("dead");
}
else
{
nav.enabled = true;
nav.SetDestination(player.transform.position);
gameObject.GetComponent<Animator>().SetTrigger("run");
}
}
}
if(dist > Radius)
{
nav.enabled = false;
gameObject.GetComponent<Animator>().SetTrigger("idle");
}
}
}
Hang this script on different enemies, after hitting the hp should be taken from a specific enemy, not all.I tried to convert health to static - it didn't help. I made the private variable-it didn't help either. I searched for this answer on the Internet.
As this is not the full code, I assume a few things. Please correct me if I'm wrong.
It seems like you create a HitEffect(Clone) when the bullet hits the enemy, right?
With this approach you the enemy does never know if the HitEffect which was created is next to it or to another player.
It would be easier to do this with physics. Please check on the OnCollisionEnter Function.
This function can be set eather to the enemy or the bullet, (I would do it to the bullet for Class based programming reasons) and check if the other part is a enemy.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class bullet_collision : MonoBehaviour
{
public int damage = 25;
void OnCollisionEnter(Collision collision)
{
monster_animation m = collision.GetComponent<monster_animation>();
if (m != null)
{
m.health -= damage;
}
}
}
The function IncreaseRadius in OrbitFireball script attached to CircleMovementTarget GameObject when called from editProperties Script attached to Radius (+) GameObject does not return the change in values in editor or the original script i.e. OrbitFireball (see on the right in the script OribtFireball, OrbitDistance = 0.1) even when the Console returns the changes just fine (see the console the values increase on hitting the Radius (+) icon).
Unity Version Used: 2017.2.1f1
...
using HoloToolkit.Unity.InputModule;
using UnityEngine;
using System.Collections;
public class OrbitFireball : MonoBehaviour, IInputClickHandler {
public Transform target;
public float orbitDistance = 0.1f;
public float orbitDegreesPerSec = 90.0f;
public GameObject Ball;
// Use this for initialization
void Start () {
}
void Orbit()
{
if(target != null)
{
// Keep us at orbitDistance from target
transform.position = target.position + (transform.position - target.position).normalized * orbitDistance;
transform.RotateAround(target.position, Vector3.back, orbitDegreesPerSec * Time.deltaTime);
// Ball up and down
Ball.transform.position = new Vector3(transform.position.x, transform.position.y, target.position.z);
}
}
// Update is called once per frame
void Update () {
Orbit();
}
public void increaseRadius()
{
if (orbitDistance <= 0.3f)
{
orbitDistance += 0.1f;
Debug.Log(orbitDistance);
}
}
public void OnInputClicked(InputClickedEventData eventData)
{
throw new System.NotImplementedException();
}
}
...
using System.Collections;
using System.Collections.Generic;
using HoloToolkit.Unity.InputModule;
using UnityEngine;
public class editProperties : OrbitFireball, IInputClickHandler {
public void OnInputClicked(InputClickedEventData eventData)
{
if (gameObject.tag == "RadiusPlus")
{
increaseRadius();
}
}
}
I'm making a target in Unity that looks like a dartboard with three different levels of scoring depending on where you shoot. The issue is that the Score Text wont change when I shoot on the target. I'm a novice and I "translated" below code from Javascript and wondering if you experts could see
if there is any issues with the code?
GlobalScore (attached this to an empty gameObject. I draged the text 'ScoreNumber' to ScoreText slot in Unity)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GlobalScore : MonoBehaviour {
public static int CurrentScore;
public int InternalScore;
public GameObject ScoreText;
void Update () {
InternalScore = CurrentScore;
ScoreText.GetComponent<Text>().text = "" + InternalScore;
}
}
ZScore25 (created 3 scripts (ZScore25, ZScore50, ZScore100) which I attached to the three cylinder gameObject I created)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ZScore25 : MonoBehaviour
{
void DeductPoints(int DamageAmount)
{
GlobalScore.CurrentScore += 25;
}
}
HandgunDamage Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HandGunDamage : MonoBehaviour {
public int DamageAmount = 5;
public float TargetDistance;
public float AllowedRange = 15.0f;
void Update () {
if (GlobalAmmo.LoadedAmmo >= 1) {
if (Input.GetButtonDown("Fire1"))
{
RaycastHit Shot;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out Shot))
{
TargetDistance = Shot.distance;
if (TargetDistance < AllowedRange)
{
Shot.transform.SendMessage("DeductPoints", DamageAmount, SendMessageOptions.DontRequireReceiver);
}
}
}
}
}
}
Debug.Log (or breakpoints) help you to see where the problem lies. I tested your case with minor changes and the score text value was changing.
I replaced ZScore25,50,100 scripts with a single ZScore script that has score as public field which you can set in the editor.
public class ZScore : MonoBehaviour {
public int Score;
public void DeductPoints() {
Debug.Log("CurrentScore += " + Score);
GlobalScore.CurrentScore += Score;
}
}
..and then I used raycast (the example script below was attached to camera):
void Update () {
if (Input.GetMouseButtonDown(0)) {
var lookAtPos = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, Camera.main.nearClipPlane));
transform.LookAt (lookAtPos);
RaycastHit Shot;
if (Physics.Raycast(transform.position, transform.forward, out Shot))
{
Debug.Log ("Raycast hit");
var score = Shot.transform.GetComponent<ZScore> ();
if (score != null) {
Debug.Log ("Hit ZScore component");
score.DeductPoints ();
}
}
}
}
I am making a game like 2 cars. And I have written code to create a instantiater. It is a car game and there are 4 lanes. Let me show you a picture of my game and yeah this is solely for practise.
Player should avoid square objects and eat circle objects but sometimes 2 square objects get spawned in a same lane making impossible for player to win. I have written this script to control that but I failed. Please help me. At least have a check to my DetectSameLaneFunction(). And tell me what I am doing wrong.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawner : MonoBehaviour {
public GameObject[] objects;
public float delaytime = 2f; // this is separate for each prefab with which script is attaches
public float spawnrate = 1f; // this is separate for each prefab with which script is attaches
public static int lastgameobjectindex;
public static GameObject lastgameobject;
public static GameObject SecondLastGameObject;
private float loadingtime;
private GameObject go; // just a temporary variable
public static List<GameObject> spawnobjects = new List<GameObject>();
// Use this for initialization
void Start () {
loadingtime = delaytime;
}
// Update is called once per frame
void Update () {
if (Time.time > loadingtime)
{
float randomness = spawnrate * Time.deltaTime;
if ( randomness < Random.value)
{
Spawners();
}
NextLoadTime();
}
}
private void Spawners()
{
int spawnnumber = Random.Range(0, 2);
GameObject go = Instantiate(objects[spawnnumber]) as GameObject;
go.transform.position = this.transform.position;
spawnobjects.Add(go);
Debug.Log(spawnobjects[spawnobjects.Count-1]);
DetectSameLaneObjects();
/* if (spawnobjects.Count > 4)
{
spawnobjects.RemoveAt(0);
}*/
}
private void DetectSameLaneObjects()
{
if (spawnobjects.Count > 3)
{
lastgameobject = spawnobjects[spawnobjects.Count - 1];
SecondLastGameObject = spawnobjects[spawnobjects.Count - 2];
lastgameobjectindex = spawnobjects.Count - 1;
if (SecondLastGameObject.transform.position.x != lastgameobject.transform.position.x
)
{
if (Mathf.Abs(lastgameobject.transform.position.x- SecondLastGameObject.transform.position.x) < 2.3f)
{
Debug.Log("Destroy function getting called");
Destroy(spawnobjects[lastgameobjectindex]);
spawnobjects.RemoveAt(lastgameobjectindex);
}
}
}
}
void OnDrawGizmos()
{
Gizmos.DrawWireSphere(this.transform.position, 0.6f);
}
void NextLoadTime()
{
loadingtime = Time.time + delaytime;
}
}