I'm writing a script for my learning project, it's a 3D fireballs mobile game copy.
My task to implement a mechanic of ball bouncing back from an obstacle. There are simpler ways, but, unfortunately I have to use the one attached. When I try to use method Evaluate I'm having this kind of log
1 In JB Rider it is:
Cannot resolve symbol 'Evaluate'
In Unity it is:
Assets\Scripts\Physics\DirectionalBounce.cs(56,48): error CS1061:
'Animation' does not contain a definition for 'Evaluate' and no
accessible extension method 'Evaluate' accepting a first argument of
type 'Animation' could be found (are you missing a using directive or
an assembly reference?)
using System.Collections;
using Coroutines;
using Structures;
using UnityEngine;
namespace Physics
{
[System.Serializable]
public class DirectionalBouncePreferences
{
public float Duration;
public float Height;
public Animation Trajectory;
public DirectionalBouncePreferences(float duration, float height, Animation trajectory)
{
Duration = duration;
Height = height;
Trajectory = trajectory;
}
}
public class DirectionalBounce
{
private readonly Transform _bouncer;
private CoroutineExecutor _coroutineExecutor;
private readonly DirectionalBouncePreferences _preferences;
public DirectionalBounce(Transform bouncer, CoroutineExecutor coroutineExecutor, DirectionalBouncePreferences preferences)
{
_bouncer = bouncer;
_coroutineExecutor = coroutineExecutor;
_preferences = preferences;
}
public void BounceTo(Vector3 target, Vector3 startPosition) =>
_coroutineExecutor.Start(InerpolatePositionTo(target, startPosition));
private IEnumerator InerpolatePositionTo(Vector3 target, Vector3 startPosition)
{
var timer = new UnityTimer();
timer.Start(_preferences.Duration);
while (timer.IsTimeUp == false)
{
float t = timer.ElapsedTimePercent;
Vector3 newPosition = CalculatePosition(target, startPosition, t);
_bouncer.transform.position = newPosition;
yield return null;
}
}
private Vector3 CalculatePosition(Vector3 target, Vector3 startPosition, float t)
{
return Vector3.Lerp(startPosition, target, t) +
Vector3.up * _preferences.Trajectory.Evaluate(t) *
_preferences.Height;
}
}
}
[enter image description here][1]
The issue appears to be that you're calling a method named Evaluate on an instance of an Animation class - which does not have a method called Evaluate.
Just a guess, but perhaps you were looking for AnimationCurve.Evaluate?
Related
I have a problem with Unity (version 2020.3.5f1 LTS). In particular, I have moved a project from a computer to another, and I have this error several times:
Error CS0229 Ambiguity between 'TimeCounter.singleton' and 'TimeCounter.singleton'
I know that this kind of error occurs when you have two different variables with the same name, as the compiler cannot distinguish between them; however, I do not have this particular situation. In fact, I have only one class TimeCounter in my project, and there are no repeated variables' names.
I have tried to fix this problem by deleting the .sln project and recreating it through Unity (as suggested here), however it did not work.
The class in which the error generates is the following one:
using System.Collections;
using UnityEngine;
using EventSystem2;
public class TimeCounter : MonoBehaviour
{
[SerializeField] float minutesToPlay = 2f;
float currentTime = 0f;
public GameEvent endedTimeEvent;
private static TimeCounter singleton;
void Awake()
{
if (!singleton)
{
singleton = this;
DontDestroyOnLoad(this);
}
}
void Start()
{
currentTime = minutesToPlay * 60f;
}
IEnumerator Timer()
{
while (true)
{
if (currentTime > 0f)
{
currentTime -= 1f;
print("current time: " + currentTime);
}
else
{
endedTimeEvent.Raise();
}
yield return new WaitForSeconds(1);
}
}
public void StartTimer()
{
StartCoroutine(nameof(Timer));
}
public void StopTimer()
{
StopCoroutine(nameof(Timer));
}
public void ResetTimer()
{
currentTime = minutesToPlay * 60f;
}
public float GetTimeToPlayInMilliseconds() => (this.minutesToPlay * 60000);
public float GetTimeToPlayInSeconds() => (this.minutesToPlay * 60);
}
This is the list of ambiguity errors I have:
Problem solved! The TimeCounter.cs script was duplicated inside the Unity project (I do not know why it happened), therefore the compiled did not know to which version I was referring to.
How can you pass a Monobehaviour inside an instance of a non Monobehaviour class? I found this link where TonyLi mentions that you can pass a Monobehaviour to start and stop coroutines inside a instance of a class, but he does not show how you can do that. He does this theEvent.StartEvent(myMonoBehaviour); but he does not show where he gets myMonobehaviour from. I looked around on the internet but I cannot seem to find how.
Edit
Here is what I am trying to do. I want to run a coroutine inside an instance of a class. I also want to be able to stop the coroutine inside the instance of the class. I want to do it this way so that I don't have any objects in my scene that have large managers and also so that I can reuse the code for any object that I want to pingpong in this way. The code moves a Gameobject in one direction then takes a break and moves it in the other direction and takes a break again etc. But I cannot start the coroutine from outside the class.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
[RequireComponent (typeof(Image))]
public class SpecialBar : MonoBehaviour {
public float rangeX;
public float breakTime;
public float step;
float startProgress = 0.5f;
PingPongGameObject pingPonger;
Color[] teamColors = new Color[]{new Color(255,136,0),new Color(0,170,255)};
void Start()
{
for(int i = 0; i < teamColors.Length; ++i)
{
teamColors[i] = StaticFunctions.NormalizeColor (teamColors[i]);
}
pingPonger = new PingPongGameObject (gameObject.transform.position,
new Vector3(rangeX,0.0f,0.0f),
gameObject,
startProgress,
breakTime,
step
);
}
}
The second class is where my coroutine is in.
public class PingPongGameObject
{
float step;
Vector3 center;
Vector3 range;
GameObject ball;
float progress;
float breakTime;
Vector3 endPos;
Vector3 oppositePosition;
public PingPongGameObject(Vector3 _center, Vector3 _range, GameObject _ball, float _startProgress, float _breakTime, float _step)
{
center = _center;
range = _range;
ball = _ball;
progress = _startProgress;
breakTime = _breakTime;
step = _step;
endPos = center - range;
oppositePosition = center + range;
// This is where I want to start the coroutine
}
public IEnumerator PingPong()
{
while (progress < 1) {
progress += Time.deltaTime * step;
Vector3 newPos = Vector3.Lerp (oppositePosition, endPos, progress);
ball.transform.position = newPos;
yield return null;
}
Vector3 temp = endPos;
endPos = oppositePosition;
oppositePosition = temp;
progress = 0;
yield return new WaitForSeconds (breakTime);
yield return null;
}
public float Step
{
set{step = value;}
}
public void StopCoroutine()
{
// This is where I want to stop the coroutine
}
}
TonyLi mentions that you can pass a Monobehaviour to start and stop
coroutines inside a instance of a class, but he does not show how you
can do that. He does this
You are can do that with the this keyword. The this keyword will get the current instance of MonoBehaviour.
In this example there's a tree, which happens to have a component MonoScript:
That particular instance of MonoScript can if it wants (since it's a c# program) instantiate a general c# class, NonMonoScript:
Class to pass MonoBehaviour from:
public class MonoScript : MonoBehaviour
{
void Start()
{
NonMonoScript nonMonoScript = new NonMonoScript();
//Pass MonoBehaviour to non MonoBehaviour class
nonMonoScript.monoParser(this);
}
}
Class that receives pass MonoBehaviour instance:
public class NonMonoScript
{
public void monoParser(MonoBehaviour mono)
{
//We can now use StartCoroutine from MonoBehaviour in a non MonoBehaviour script
mono.StartCoroutine(testFunction());
//And also use StopCoroutine function
mono.StopCoroutine(testFunction());
}
IEnumerator testFunction()
{
yield return new WaitForSeconds(3f);
Debug.Log("Test!");
}
}
You can also store the mono reference from the monoParser function in a local variable to be re-used.
Based on this Unity Animator API, there's a public function named IsInTransition. but why i cannot use it?
When i try to code in MonoDevelop, the Autocompletion wont work and also build was Error :
Assets/Scripts/CatAnimator.cs(32,18): error CS1061:
Type `Animator' does not contain a definition for `isInTransition'
and no extension method `isInTransition'
of type `Animator' could be found.
Are you missing an assembly reference?
any idea ?
The Complete Code :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Animator : MonoBehaviour {
Animator myAnimator;
public float speed = 10.0f;
public float jumpSpeed = 8.0f;
public float gravity = 20.0f;
private Vector3 moveDirection = Vector3.zero;
CharacterController controller;
float currSpeed, Param1;
bool Param2, Param3;
// Use this for initialization
void Start () {
controller = GetComponent<CharacterController> ();
myAnimator = GetComponent<Animator> ();
}
// Update is called once per frame
void Update () {
Param1 = 0;
Param2 = false;
Param3 = false;
if (controller.isGrounded) {
//==
}
if (myAnimator.IsInTransition (0)) { //ERROR HERE...
}
}//==update
}//==class
The problem here was the fact that you are making a class named Animator. However there is an animator class already provided by Unity. When you declare an object of type Animator (Animator myAnimator;), the compiler thinks of your class instead of the class provided by Unity. And in your class there is no IsInTransition() method to use. To fix this simply rename your class to MyAnimator for example.
I'm making my first game and I have some trouble with my sound scripting. What i want to do is, when the GameObject "key" is active in the hierarchy i want the sound to play once. here is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class keyUnlock : MonoBehaviour
{
public GameObject key;
public AudioSource clip;
int keySoundsTotalCount = 1;
int keySoundsPlayed = 0;
public void KeyUnlocks ()
{
if (key.activeInHierarchy == true)
{
AudioSource.PlayClipAtPoint (clip, transform.position); // <---here
keySoundsPlayed++;
}
}
}
so in UnityEngine i get these two errors:
Assets/Scripts/keyUnlock.cs(17,16): error CS1502: The best overloaded method match for `UnityEngine.AudioSource.PlayClipAtPoint(UnityEngine.AudioClip, UnityEngine.Vector3)' has some invalid arguments
Assets/Scripts/keyUnlock.cs(17,33): error CS1503: Argument `#1' cannot convert `UnityEngine.AudioSource' expression to type `UnityEngine.AudioClip'
This is the AudioSource.PlayClipAtPoint function blueprint:
public static void PlayClipAtPoint(AudioClip clip, Vector3 position, float volume = 1.0F);
You are currently passing the AudioSource to the clip parameter which expects AudioClip.
Simply change public AudioSource clip; to public AudioClip clip;.
I have a problem getting a variable from script from another GameObject.. I have used this type of referring before and I know how it works, but for some reason it's saying it can't find the script I am referring to.
The code that is referring to the other code (if statements at the start of CanHearPlayer()):
using UnityEngine;
using System.Collections;
public class EnemySight : MonoBehaviour {
public GameObject Player;
public float fieldOfViewDegrees = 30;
public float visibilityDistance = 50;
public bool SeeingPlayer;
public float deathDistance;
public float hearDistance;
void Update(){
SeeingPlayer = CanSeePlayer();
float Distance = Vector3.Distance(transform.position, Player.transform.position);
if ((SeeingPlayer == true)) {
transform.LookAt(Player.transform.position);
if (Distance < deathDistance){
Debug.Log("You died");
//Game over sequence starts here
}
}
if (CanHearPlayer () == true) {
Debug.Log ("I can hear you.");
}
}
protected bool CanSeePlayer()
{
RaycastHit hit;
Vector3 rayDirection = Player.transform.position - transform.position;
if ((Vector3.Angle(rayDirection, transform.forward)) <= fieldOfViewDegrees * 0.5f)
{
// Detect if player is within the field of view
if (Physics.Raycast(transform.position, rayDirection, out hit, visibilityDistance))
{
return (hit.transform.CompareTag("Player"));
}
}
return false;
}
protected bool CanHearPlayer(){
RaycastHit hit;
Vector3 rayDirection = Player.transform.position - transform.position;
if (Player.GetComponent<FirstPersonController>().MakingWalkingSound == true) {
hearDistance = 50;
} else {
hearDistance = 5;
}
if (Player.GetComponent<FirstPersonController>().MakingRunningSound == true) {
hearDistance = 100;
}
if (Physics.Raycast(transform.position, rayDirection, out hit, hearDistance))
{
return (hit.transform.CompareTag("Player"));
}
return false;
}
}
The public GameObject 'Player' is defined in Unity as the object which contains the 'FirstPersonController' script as a component.
Code it is referring to (part of it):
public class FirstPersonController : MonoBehaviour
{
public bool MakingWalkingSound;
public bool MakingRunningSound;
private void GetInput(out float speed)
{
// Read input
float horizontal = CrossPlatformInputManager.GetAxis("Horizontal");
float vertical = CrossPlatformInputManager.GetAxis("Vertical");
MakingWalkingSound = !(horizontal == 0 && vertical == 0);
MakingRunningSound = Input.GetKey(KeyCode.LeftShift);
}
The errors read: Assets/EnemySight.cs(53,41): error CS0246: The type or namespace name 'FirstPersonController' could not be found. Are you missing a using directive or an assembly reference?
And: Assets/EnemySight.cs(59,41): error CS0246: The type or namespace name 'FirstPersonController' could not be found. Are you missing a using directive or an assembly reference?
These lines correspond to the first two if-statements in CanHearPlayer.
What am I doing wrong? I've searched on Google and StackOverflow, but I cannot find what the problem is..
Thanks!
If there is some namespace declaration on your FirstPersonController class you need to declare using on your EnemySight code. Just like:
namespace MyNamespace.Blah {
public class FirstPersonController : MonoBehaviour {
...
}
}
and...
using MyNamespace.Blah;
public class EnemySight : MonoBehaviour {
...
}
for monodevelop you can use alt+spacebar when declaring classes that are not already in your using scope and it will place using on top of the class for you.