Adding key functionality to OnTriggerEnter - c#

I have 2 scripts which are working almost perfectly for me.
PlayerPositionCorrection on player :
public class PlayerPositionCorrection : MonoBehaviour
{
Transform _playerTransform;
public float _xAxys;
public float _newXAxys;
private void Start()
{
_playerTransform = GetComponent<Transform>();
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("ChangePlayerPosition"))
{
Debug.Log("Check if Collided With : " + other.gameObject.name);
_newXAxys = other.GetComponent<PositionCorrector>()._newXAxys;
Debug.Log("New XAxys value : " + _newXAxys);
}
}
}
and PositionCorrector on object with collider :
public class PositionCorrector : MonoBehaviour
{
public float _newXAxys = 4;
public Vector3 _playerPostion;
//public int _optionNumber = 1;
[SerializeField] bool _isInTriggerZone = false;
private void Update()
{
}
private void OnTriggerEnter(Collider other)
{
if (Input.GetKeyDown("p") && other.CompareTag("Player"))
{
_playerPostion = other.transform.position;
_playerPostion = new Vector3(_newXAxys, _playerPostion.y, _playerPostion.z);
}
}
}
I try to add to this script PositionCorrector one future when character/player collide with object AND PRESS ANY KEY (for this purpose can be 'P') then change his position. But when character collide witch object (character) don't wait for press key just immediately changing position.
And this is what I added :
private void OnTriggerEnter(Collider other)
{
if (Input.GetKeyDown("p") && other.CompareTag("Player"))
{
_playerPostion = other.transform.position;
_playerPostion = new Vector3(_newXAxys, _playerPostion.y, _playerPostion.z);
}
}

Related

How do I do the check once?

I have a condition that should check whether it is true or false. I did this:
void Update()
{
if (Slot.SlotBool == true)
{
score++;
Debug.Log("OK! " + score);
}
}
But I want him to check without pressing the button, and put it in Update(), but then Score was increasing every second... Is there any other way to do it?
I have 3 scripts, the first one is needed to move an object, get a starting position, etc. It looks like this:
public class DManager : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler, IPointerClickHandler
{
public static GameObject objBeingDraged;
private Vector2 startPosition;
private Transform startParent;
private CanvasGroup canvasGroup;
private Transform itemDraggerParent;
void Start()
{
canvasGroup = GetComponent<CanvasGroup>();
itemDraggerParent = GameObject.FindGameObjectWithTag("ItemDraggerParent").transform;
}
public void OnBeginDrag(PointerEventData eventData)
{
objBeingDraged = gameObject;
startPosition = transform.position;
startParent = transform.parent;
transform.SetParent(itemDraggerParent);
canvasGroup.blocksRaycasts = false;
}
public void OnDrag(PointerEventData eventData)
{
transform.position = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
public void OnEndDrag(PointerEventData eventData)
{
objBeingDraged = null;
canvasGroup.blocksRaycasts = true;
if (transform.parent == itemDraggerParent)
{
transform.position = startPosition;
transform.SetParent(startParent);
}
}
public void OnPointerClick(PointerEventData eventData)
{
transform.rotation *= Quaternion.Euler(0,0, -90);
}
}
The second one is needed so that when the object is released:
public class Puzzle : MonoBehaviour, IDropHandler
{
public void OnDrop(PointerEventData eventData)
{
if (DManager.objBeingDraged == null) return;
DManager.objBeingDraged.transform.SetParent(transform);
}
}
And the third one is needed already in order to get an object and compare the resulting object name. I could put score accruals here, but here he checks every element
int score=0;
public static bool f=false;
public void OnDrop(PointerEventData eventData)
{
if (!item)
{
item = DManager.objBeingDraged;
if (item.name== this.gameObject.name)
{
if (item.transform.rotation == this.gameObject.transform.rotation)
{
f = true;
Debug.Log(f);
score++;
Debug.Log(score);
}
}
item.transform.SetParent(transform);
item.transform.position = transform.position;
}
}
void Update()
{
if (item != null && item.transform.parent != transform)
{
item = null;
}
}
So I created another script where points are already awarded
you can add another boolean to check if the score was already incremented.
private bool incrementedBool = false;
void Update()
{
if(incrementedBool == false)
{
incrementedBool = true;
if (Slot.SlotBool == true)
{
score++;
Debug.Log("OK! " + score);
}
}
}
Then, if you want to incremente another time the score for any reason, you can reset the boolean like that :
incrementedBool = false;

How can I update my newDiamondText counter on my UI to go to zero?

public class BuyableItem : MonoBehaviour
{
public float PickUpRadius = 1f;
public InventoryItemData ItemData;
private SphereCollider myCollider;
private void Awake()
{
myCollider = GetComponent<SphereCollider>();
myCollider.isTrigger = true;
myCollider.radius = PickUpRadius;
}
private void OnTriggerEnter(Collider other)
{
var inventory = other.transform.GetComponent<InventoryHolder>();
if (!inventory) return;
if (inventory.InventorySystem.AddToInventory(ItemData, 1))
{
Destroy(this.gameObject);
}
}
public static void UpdateDiamondText(PlayerInventory playerInventory)
{
InventoryUI.newDiamondText.text = playerInventory.NumberOfDiamonds.ToString();
}
}
Based off of this, how would I be able to make the counter of my InventoryUI newDiamondText script reach zero when picking up an item?

I can't Save Multiple PlayerPrefs on my Main Menu

Hi I'm a student in game development, making a game where players can grab certain amounts of coins on each maps, every maps has different type of coins data, like a highscore. But it only saves 1 playerprefs only. Why is that happening?
This is my Scene Management Script;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;
public class changeScene : MonoBehaviour
{
public TextMeshProUGUI desertCoinAmount;
public TextMeshProUGUI plainsCoinAmount;
void Update()
{
desertCoinAmount.text = PlayerPrefs.GetInt("DesertCoins").ToString();
plainsCoinAmount.text = PlayerPrefs.GetInt("PlainsCoins").ToString();
}
public void mainMenu()
{
SceneManager.LoadScene("mainMenu");
PlayerPrefs.Save();
}
public void desertLevel()
{
SceneManager.LoadScene("ancientDesertLEVEL");
Time.timeScale = 1f;
PlayerPrefs.Save();
}
public void plainsLevel()
{
SceneManager.LoadScene("Plain Biome");
Time.timeScale = 1f;
PlayerPrefs.Save();
}
public void jungleLevel()
{
SceneManager.LoadScene("Jungle Biome");
Time.timeScale = 1f;
}
}
And This is my PlayerController;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PlayerController : MonoBehaviour
{
public GameObject winPopup, losePopup;
public GameObject heart1, heart2, heart3;
public float gravityScale = 10f;
private Rigidbody rb;
public TextMeshProUGUI coinText;
public AudioSource coinSound;
int coin_sumDesert;
int coin_sumPlains;
int life_sum = 3;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
GetComponent<Rigidbody>().AddForce(Physics.gravity * gravityScale, ForceMode.Force);
}
void Update()
{
PlayerPrefs.SetInt("DesertCoins", coin_sumDesert);
PlayerPrefs.SetInt("PlainsCoins", coin_sumPlains);
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Coins")
{
coin_sumDesert++;
coinText.text = coin_sumDesert.ToString();
Destroy(other.gameObject);
coinSound.Play();
}
if (other.gameObject.tag == "PlainsCoins")
{
coin_sumPlains++;
coinText.text = coin_sumPlains.ToString();
Destroy(other.gameObject);
coinSound.Play();
}
if (other.gameObject.tag == "finishLine")
{
winPopup.SetActive(true);
}
if (other.gameObject.tag == "obstacles")
{
Debug.Log("Collide Detected");
life_sum--;
if (life_sum == 2)
{
heart1.SetActive(false);
}
else if (life_sum == 1)
{
heart2.SetActive(false);
}
else if (life_sum == 0)
{
heart3.SetActive(false);
losePopup.SetActive(true);
Time.timeScale = 0.0f;
}
}
}
}
I would appreciate the reply (this is my first time using StackOverflow xD)
If you have multiple PlayerController then obviously they write to the same PlayerPrefs keys.
Whenever you save a player's data, make sure you differentiate them e.g. Score1, Score2, etc.
This is a way among many others to achieve it:
The player, very simple, append index to player pref to differentiate among many:
public sealed class Player : MonoBehaviour
{
private const string ChocolateBarsKey = "ChocolateBars";
[SerializeField]
[HideInInspector]
private int Index;
private int ChocolateBars
{
get => GetInt(ChocolateBarsKey);
set => SetInt(ChocolateBarsKey, value);
}
private int GetInt([NotNull] string key, int defaultValue = default)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
return PlayerPrefs.GetInt($"{key}{Index}", defaultValue);
}
private void SetInt([NotNull] string key, int value)
{
PlayerPrefs.SetInt($"{key}{Index}", value);
}
[NotNull]
internal static Player Create([NotNull] GameObject parent, int index)
{
if (parent == null)
throw new ArgumentNullException(nameof(parent));
var controller = parent.AddComponent<Player>();
controller.name = $"{nameof(Player)} {index}";
controller.Index = index;
return controller;
}
}
The factory, scriptable singleton won't lose state on assembly reload, whereas if you'd used a static int for player count, it would reset itself to zero at assembly reload because static fields are not serialized by Unity.
public sealed class PlayerFactory : ScriptableSingleton<PlayerFactory>
{
[SerializeField]
private int PlayerCount;
[NotNull]
public Player Create(GameObject parent)
{
return Player.Create(parent, ++PlayerCount);
}
}
Now if you don't want to store score data within Player, it'll be another pattern. I leave that to you as an exercise.

Unity 2d game Player and enemy not moving

I have been following a tutorial on a unity 2d game. The player and the enemy inherit from a base class known as MovingObject. Everything in the game works fine except that the player and the enemy can't move. Here are the scripts. The movement happens in a gridlike tile system.
This is the original tutorial series. Try going over the moving object, player, and enemy tutorials.
https://www.youtube.com/playlist?list=PLX2vGYjWbI0SKsNH5Rkpxvxr1dPE0Lw8F
Base MovingObject class:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class MovingObject : MonoBehaviour {
public float moveTime = 0.1f;
public LayerMask blockinglayer;
private BoxCollider2D boxCollider;
private Rigidbody2D rb2D;
private float inverseMoveTime;
// Use this for initialization
protected virtual void Start () {
boxCollider = GetComponent<BoxCollider2D>();
rb2D = GetComponent<Rigidbody2D>();
inverseMoveTime = 1f / moveTime;
}
protected bool Move(int xDir, int yDir, out RaycastHit2D hit)
{
Vector2 start = transform.position;
Vector2 end = start + new Vector2(xDir, yDir);
boxCollider.enabled = false;
hit = Physics2D.Linecast(start, end, blockinglayer);
boxCollider.enabled = true;
if (hit.transform == null)
{
StartCoroutine(SmoothMovement(end));
return true;
}
return false;
}
protected IEnumerator SmoothMovement(Vector3 end)
{
float sqrRemainingDistance = (transform.position - end).sqrMagnitude;
while (sqrRemainingDistance > float.Epsilon)
{
Vector3 newPosition = Vector3.MoveTowards(rb2D.position, end, inverseMoveTime * Time.deltaTime);
rb2D.MovePosition(newPosition);
sqrRemainingDistance = (transform.position - end).sqrMagnitude;
yield return null;
}
}
protected virtual void AttemptMove<T>(int xDir, int yDir)
where T : Component
{
RaycastHit2D hit;
bool canMove= Move(xDir, yDir, out hit);
if (hit.transform == null)
{
return;
}
T hitComponent = hit.transform.GetComponent<T>();
if(!canMove && hitComponent != null)
{
OnCantMove(hitComponent);
}
}
protected abstract void OnCantMove<T>(T component)
where T : Component;
// Update is called once per frame
}
Player Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Player : MovingObject {
public int wallDamage = 1;
public int pointsPerFood = 10;
public int pointsPerSoda = 20;
public float restartLevelDelay = 1f;
private Animator animator;
private int food;
// Use this for initialization
protected override void Start () {
animator = GetComponent<Animator>();
food = GameManager.instance.playerFoodPoints;
base.Start();
}
private void OnDisable()
{
GameManager.instance.playerFoodPoints = food;
}
// Update is called once per frame
void Update () {
if (GameManager.instance.playersTurn)
{
return;
}
int horizontal = 0;
int vertical = 0;
horizontal = (int)Input.GetAxisRaw("Horizontal");
vertical = (int)Input.GetAxisRaw("Vertical");
if (horizontal != 0)
{
vertical = 0;
}
if(horizontal!=0 || vertical != 0)
{
AttemptMove<Wall>(horizontal, vertical);
}
}
protected override void OnCantMove<T>(T component)
{
Wall hitwall = component as Wall;
hitwall.damageWall(wallDamage);
animator.SetTrigger("playerChop");
}
protected override void AttemptMove<T>(int xDir, int yDir)
{
food--;
base.AttemptMove<T>(xDir, yDir);
RaycastHit2D hit;
CheckIfGameOver();
GameManager.instance.playersTurn = false;
}
public void LoseFood(int loss)
{
animator.SetTrigger("playerHit");
food -= loss;
CheckIfGameOver();
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Exit")
{
Invoke("Restart", restartLevelDelay);
enabled = false;
}
else if (other.tag == "Food")
{
food += pointsPerFood;
other.gameObject.SetActive(false);
}
else if (other.tag == "Soda")
{
food += pointsPerSoda;
other.gameObject.SetActive(false);
}
}
private void Restart()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
private void CheckIfGameOver()
{
if (food <= 0)
{
GameManager.instance.GameOver();
}
}
}
Enemy Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MovingObject {
public int playerDamage;
private Animator animator;
private Transform target;
private bool skipmove;
// Use this for initialization
protected override void Start () {
GameManager.instance.AddEnemyToList(this);
animator = GetComponent<Animator>();
target = GameObject.FindGameObjectWithTag("Player").transform;
base.Start();
}
protected override void AttemptMove<T>(int xDir, int yDir)
{
if (skipmove)
{
skipmove = false;
return;
}
base.AttemptMove<T>(xDir, yDir);
}
public void MoveEnemy()
{
int xDir = 0;
int yDir = 0;
if (Mathf.Abs(target.position.x - transform.position.x) < float.Epsilon)
{
yDir = target.position.y > transform.position.y ? 1 : -1;
}
else
{
xDir = target.position.x > transform.position.x ? 1 : -1;
AttemptMove<Player>(xDir,yDir);
}
}
protected override void OnCantMove<T>(T component)
{
Player hitplayer = component as Player;
animator.SetTrigger("enemyAttack");
hitplayer.LoseFood(playerDamage);
}
}
I'm not sure which whether the player or enemy have an issue of the base script. Can anyone help.
A few Observations (Hopefully it helps):
MovingObject.cs - Inside of Update(), should it not be this?
if (!GameManager.instance.playersTurn)
Note I added a "!" before GameManager
Player.cs - in AttemptMove(), you need to call Move()... like this
Move (xDir, yDir, out hit);
Enemy.cs
1) At the end of AttemptMove(), there should be:
skipMove = true;
2) In MoveEnemy(), at the end, this code should NOT be in the else, but after the else:
AttemptMove<Player>(xDir,yDir);

"Cannot reuse the bullets in obectpool."

When bulletpool is being instantiated, I can shoot bullets. But when all the bullets are done instantiated, I can't shoot the bullet. IDK where is the porblem..
BulletPoolScript:
public class scriptBulletPool : MonoBehaviour
{
private static scriptBulletPool myInstance;
public static scriptBulletPool MyInstance
public GameObject bulletPrefab;
public List<GameObject> bulletPool;
public int poolSize;
{
get
{
return myInstance;
}
}
private void Awake()
{
if (myInstance == null)
{
myInstance = this;
} else if(myInstance != this)
{
Debug.LogError("Obj 1:", gameObject);
Debug.LogError("Obj 2:", myInstance.gameObject);
}
instantiatePool();
}
private void instantiatePool()
{
bulletPool = new List<GameObject>();
for (int i=0; i<poolSize; i++)
{
GameObject newBullet = Instantiate(bulletPrefab);
bulletPool.Add(newBullet);
newBullet.SetActive(false);
}
}
public GameObject getBullet(Vector3 targetPos, Quaternion targetRot)
{
GameObject newBullet = bulletPool[bulletPool.Count - 1];
newBullet.transform.position = targetPos;
newBullet.transform.rotation = targetRot;
newBullet.SetActive(true);
bulletPool.Remove(newBullet);
return newBullet;
}
public void returnBullet(GameObject bullet)
{
bulletPool.Add(bullet);
bullet.SetActive(false);
}
}
ShootScript:
public class scriptShoot : MonoBehaviour
{
public GameObject bulletSpawnPoint;
void Update()
{
shoot();
}
private void shoot()
{
if (Input.GetMouseButtonDown(0))
{
scriptBulletPool.MyInstance.getBullet(bulletSpawnPoint.transform.position, bulletSpawnPoint.transform.rotation);
}
}
}
BulletScript:
public class scriptBullet : MonoBehaviour
{
public GameObject bullet;
public float maxDistance;
void Update()
{
transform.Translate(Vector3.forward * 7 * Time.deltaTime);
maxDistance += 1 * Time.deltaTime;
if (maxDistance >= 5)
{
scriptBulletPool.MyInstance.returnBullet(bullet);
}
}
}
The problem is probably the scriptBullet.maxDistance.
You increment it in every update, and eventually pool the bullet.
When you need a bullet, you unpool it, but the maxDistance is never reset, resulting in the bullet being pooled again immediately.

Categories