What to do when VSCode is not giving me an error? - c#

I'm new to C# (did some stuff in python earlier) and i cant get this code to work. Im making a mobile game and this script should run a timer, check if the timer is equal to "SaleTime" and if it is add money to the users balance and reset the timer to 0.
As VSCode is not giving me any errors i dont know what the problem is and after looking around i cant find a solution to it.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Threading;
public class Sales : MonoBehaviour
{
public float Timer = 0.0f;
public float SaleTime = 5.0f;
public float ProductValue = 5.0f;
public float Money = 1000.0f;
void Start()
{
StartCoroutine(time());
}
public void GameTime()
{
Timer += 1;
}
IEnumerator time()
{
while (true)
{
GameTime();
yield return new WaitForSeconds(1);
}
}
public void SaleFunction()
{
if (Timer == SaleTime)
{
Timer = 0.0f;
Money = Money + ProductValue;
}
}
}

You are not calling SaleFunction(), so the program never checks the condition.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Threading;
public class Sales : MonoBehaviour
{
public float Timer = 0.0f;
public float SaleTime = 5.0f;
public float ProductValue = 5.0f;
public float Money = 1000.0f;
void Start()
{
StartCoroutine(time());
}
public void GameTime()
{
Timer += 1;
}
IEnumerator time()
{
while (true)
{
GameTime();
SaleFunction(); // Added line.
yield return new WaitForSeconds(1);
}
}
public void SaleFunction()
{
if (Timer == SaleTime)
{
Timer = 0.0f;
Money = Money + ProductValue;
}
}
}

Related

Increasing invoke spawn speed using enumerator

I'm trying to increase the spawn time of an invoke function, I'm using an IEnumerator but it's not working.
It looks like the system reads the starting spawnSpeed value and not changing it reading the IE function.
I'm not aware if there is another way to make this work.
Plz, help.
this is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObstaclesController : MonoBehaviour
{
public GameObject obstacle;
private GameObject obstacleClone;
public Transform ObstacleMarker;
private float CloneLifeTime = 4f;
float spawnSpeed;
float spawnInterval = 3;
float minSpawn = -4;
float maxSpawn = 0;
void Start()
{
spawnSpeed = 2f;
StartCoroutine("IncreaseSpeedWithInterval");
InvokeRepeating("AddingObstacle", spawnSpeed, spawnSpeed);
}
IEnumerator IncreaseSpeedWithInterval()
{
while (true)
{
yield return new WaitForSeconds(spawnInterval);
spawnSpeed *= 1.5f;
}
}
private void AddingObstacle()
{
float randomLocation = Random.Range(minSpawn, maxSpawn);
obstacleClone = Instantiate(obstacle, ObstacleMarker.position, ObstacleMarker.rotation);
obstacleClone.transform.position = new Vector3(ObstacleMarker.transform.position.x, randomLocation, ObstacleMarker.transform.position.z);
Destroy(obstacleClone, CloneLifeTime);
}
private void Update()
{
Debug.Log(spawnSpeed);
}
}
After the call to
InvokeRepeating("AddingObstacle", spawnSpeed, spawnSpeed);
any later change on spawnSpeed has no effect whatsoever .. a float is passed by value and there is no connection between the passed one and the one you later adjust!
You can instead wrap it into another Coroutine like
private IEnumerator AddingObstacleRoutine()
{
while(true)
{
yield return new WaitForSeconds (spawnSpeed);
AddingObstacle();
}
}
And instead start this routine as well using
StartCoroutine(IncreaseSpeedWithInterval());
StartCoroutine(AddingObstacleRoutine());

How can I start the coroutine with time?

using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class PlayerMouthSpeechController : MonoBehaviour
{
public TMP_Text[] texts;
public bool startTalking = false;
public float talkTime;
public float duration;
[Range(0, 100)]
public float valueRange;
private SkinnedMeshRenderer bodySkinnedMeshRenderer;
//private bool isTalking = true;
// Start is called before the first frame update
void Start()
{
bodySkinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
}
// Update is called once per frame
void Update()
{
/*if (startTalking && isTalking)
{
StartCoroutine(AnimateMouth());
StartCoroutine(TalkTime());
isTalking = false;
}
if(startTalking == false && isTalking == false)
{
isTalking = true;
}*/
}
//Lerp between startValue and endValue over 'duration' seconds
private IEnumerator LerpShape(float startValue, float endValue, float duration)
{
float elapsed = 0;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float value = Mathf.Lerp(startValue, endValue, elapsed / duration);
bodySkinnedMeshRenderer.SetBlendShapeWeight(0, value);
yield return null;
}
}
//animate open and closed, then repeat
public IEnumerator AnimateMouth()
{
while (startTalking == true)
{
yield return StartCoroutine(LerpShape(0, valueRange, duration));
yield return StartCoroutine(LerpShape(valueRange, 0, duration));
}
}
public IEnumerator TalkTime()
{
yield return new WaitForSeconds(talkTime);
startTalking = false;
}
}
I messed it all before with too many flags and in the Update() messed it too.
I want to make something simple. To be able to call from any other script to the method AnimateMouth and that the method AnimateMouth will also get a float will be the time the mouth will be animated. something like :
StartCoroutine(AnimateMouth(4f));
but I messed it all. maybe to make the AnimateMout public static or when calling from another script first to make a reference to the PlayerMouthSpeechController and then call it something like :
playerMouthSpeechController.AnimateMouth();
and something will start the AnimatedMouth coroutine. but again I messed it too much.
Update :
This is working almost perfectly as I wanted still I need to use StartCoroutine each time I want the player to start talking but it's working.
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class PlayerMouthSpeechController : MonoBehaviour
{
public TMP_Text[] texts;
public float duration;
[Range(0, 100)]
public float valueRange;
private bool startTalking = false;
private SkinnedMeshRenderer bodySkinnedMeshRenderer;
// Start is called before the first frame update
void Start()
{
bodySkinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
}
// Update is called once per frame
void Update()
{
}
//Lerp between startValue and endValue over 'duration' seconds
private IEnumerator LerpShape(float startValue, float endValue, float duration)
{
float elapsed = 0;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float value = Mathf.Lerp(startValue, endValue, elapsed / duration);
bodySkinnedMeshRenderer.SetBlendShapeWeight(0, value);
yield return null;
}
}
//animate open and closed, then repeat
public IEnumerator AnimateMouth(float TimeToTalk)
{
startTalking = true;
StartCoroutine(TalkTime(TimeToTalk));
while (startTalking == true)
{
yield return StartCoroutine(LerpShape(0, valueRange, duration));
yield return StartCoroutine(LerpShape(valueRange, 0, duration));
}
}
private IEnumerator TalkTime(float TalkTime)
{
yield return new WaitForSeconds(TalkTime);
startTalking = false;
}
}
And using it for example in another script :
At the top :
public PlayerMouthSpeechController blendShapeController;
And
StartCoroutine(blendShapeController.AnimateMouth(10f));
I wish I could do somehow that I will not start a coroutine each time and that it will start the coroutine automatic and I will only do :
blendShapeController.AnimateMouth(10f);
And it will start the coroutine in the PlayerMouthSpeechController.
Working solution as I wanted :
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class PlayerMouthSpeechController : MonoBehaviour
{
public TMP_Text[] texts;
public float duration;
[Range(0, 100)]
public float valueRange;
private bool startTalking = false;
private SkinnedMeshRenderer bodySkinnedMeshRenderer;
// Start is called before the first frame update
void Start()
{
bodySkinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
}
// Update is called once per frame
void Update()
{
}
//Lerp between startValue and endValue over 'duration' seconds
private IEnumerator LerpShape(float startValue, float endValue, float duration)
{
float elapsed = 0;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float value = Mathf.Lerp(startValue, endValue, elapsed / duration);
bodySkinnedMeshRenderer.SetBlendShapeWeight(0, value);
yield return null;
}
}
//animate open and closed, then repeat
public void AnimateMouth(float TimeToTalk)
{
StartCoroutine(StartAnimating(TimeToTalk));
}
private IEnumerator StartAnimating(float TimeToTalk)
{
startTalking = true;
StartCoroutine(TalkingTime(TimeToTalk));
while (startTalking == true)
{
yield return StartCoroutine(LerpShape(0, valueRange, duration));
yield return StartCoroutine(LerpShape(valueRange, 0, duration));
}
}
private IEnumerator TalkingTime(float TalkTime)
{
yield return new WaitForSeconds(TalkTime);
startTalking = false;
}
}
In other script/s making a reference :
public PlayerMouthSpeechController blendShapeController;
And starting
blendShapeController.AnimateMouth(10f);

Debug.Log being delayed in Unity

While trying to create a game in Unity about you building a small city I stumbled upon a problem. I'm using NavMesh to have the player lead around tiny people (called mixxes here). The NavMesh is working, just I'm trying to make the mixxes produce different materials based on the location you lead them to.
Here is my code so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class MixxScript : MonoBehaviour
{
public float speed = 5f;
public Transform target = null;
public Transform oldTarget = null;
public Transform lastPossibleSuccess;
public float range = 8.4f;
public NavMeshAgent agent;
private float countdown = 3;
void Update()
{
if (target == null)
{
return;
}
agent.SetDestination(target.position);
float distance = Vector3.Distance(transform.position, target.position);
Debug.Log(distance);
if (distance <= 2)
{
countdown -= Time.deltaTime;
if (countdown <= 0)
{
if (target.transform.name == "Factory")
{
MainScript.metal += 1;
}
if (target.transform.name == "Farm")
{
MainScript.food += 1;
}
countdown = 3;
}
}
else
{
countdown = 3;
}
}
void OnMouseDown()
{
MainScript.selectedMixx = gameObject;
}
}
And here is MainScript:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MainScript: MonoBehaviour
{
public static GameObject selectedMixx = null;
public static GameObject selectedPlatform = null;
public static float metal = 0;
public static float wood = 0;
public static float money = 0;
public static float mixxes = 1;
public static float food = 50;
public Text scoreText;
void Update()
{
scoreText.text = "Money: $" + money.ToString() + "\nFood: " + food.ToString() + "\nMetal: " + metal.ToString() + "\nWood: " + wood.ToString() + "\nMixxes: " + mixxes.ToString();
}
}
The problem is that 1) The text as shown in MainScript is not updating. 2) The Debug.Log() statement is not working so I cannot see what is wrong here.
What I've tried:
Multiple ways to measure distance
Different distance restraints (such as the one on line 28 of the first script)
Using FixedUpdate() instead of Update() (which failed completely)
Is there a solution to this?

Can't figure out how to access an int from another script

I know this question has been asked before, here and here.
But I still can't get variables from another script. I don't know what I'm doing wrong.
*(I'm really new to programming in general so I might have missed something glaringly obvious)
I keep on getting the error: The name 'points' does not exist in the current context
The slimespawner script is on the Canvas.
Sorry if the question is too simple.
here's the script I'm trying to access:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class slimespawner : MonoBehaviour
{
public int points;
public Text score;
public float xx;
public float yy;
void Start()
{
points = 0;
xx = Random.Range(-32f, 32f);
yy = Random.Range(-18.5f, 18.5f);
}
void Update()
{
score.text = "Score: " + points.ToString();
}
}
And here's the script that's trying to use the points variable.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class slimecontroller : MonoBehaviour
{
private float movespeed = 0.1f;
public slimespawner slisp;
void Start()
{
slisp = GameObject.Find("Canvas").GetComponent<slimespawner>();
}
void Update()
{
points += 1;
}
}
Your code should look as this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class slimecontroller : MonoBehaviour
{
private float movespeed = 0.1f;
public slimespawner slisp;
void Start()
{
slisp = GameObject.Find("Canvas").GetComponent<slimespawner>();
}
void Update()
{
slisp.points += 1;
}
}
Access the property with slisp.points += 1;

Method inaccessible due to its protection level

I'm currently developing within Unity 2018 and have made a script for decreasing a character's health on collision with an enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HealthManager : MonoBehaviour
{
public static int currentHealth;
public Slider healthBar;
void Awake()
{
healthBar = GetComponent<Slider> ();
currentHealth = 100;
}
void ReduceHealth()
{
currentHealth = currentHealth - 1;
healthBar.value = currentHealth;
}
void Update()
{
healthBar.value = currentHealth;
}
}
When I try to use said method in the scripting file for the enemy I get an error stating "Assets/Custom Scripts/BeetleScript.cs(46,28): error CS0122: `HealthManager.ReduceHealth()' is inaccessible due to its protection level"
The following is the enemy script initiating the variables being used and calling the method:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BeetleScript : MonoBehaviour
{
Animator animator;
public GameObject cucumberToDestroy;
public bool cherryHit = false;
public float smoothTime = 3.0f;
public Vector3 smoothVelocity = Vector3.zero;
public PointsManager _ptsManager;
public HealthManager _healthManager;
void Start()
{
animator = GetComponent<Animator>();
}
void Update()
{
if (cherryHit)
{
var cm = GameObject.Find("CucumberMan");
var tf = cm.transform;
this.gameObject.transform.LookAt(tf);
// move towards Cucumber Man
animator.Play("Standing Run");
transform.position = Vector3.SmoothDamp(transform.position, tf.position,
ref smoothVelocity, smoothTime);
}
}
// Collision Detection Test
void OnCollisionEnter(Collision col)
{
if (col.gameObject.CompareTag("Player"))
{
_healthManager = GameObject.Find
("Health_Slider").GetComponent<HealthManager>();
_healthManager.ReduceHealth();
if (!cherryHit)
{
BeetlePatrol.isAttacking = true;
var cm = GameObject.Find("CucumberMan");
var tf = cm.transform;
this.gameObject.transform.LookAt(tf);
animator.Play("Attacking on Ground");
StartCoroutine("DestroySelfOnGround");
}
else
{
animator.Play("Standing Attack");
StartCoroutine("DestroySelfStanding");
}
}
}
}
Any help to fix this would be appreciated.
Your methods are private.
You have to write public in front of the method you want to access from outside the class.
public void ReduceHealth()
{
...
}
You need to make void ReduceHealth() to be public -> public void ReduceHealth()

Categories