Why is my inspector losing reference on play? - unity3d

This is before play
This is after play.
I have a very simple script. I am using [SerializeField] on a TMP_Text file. In the inspector I have dragged the text file from the Hierarchy into the serlialized field in the inspector of my UI Controller. When I click on play, the inspector drops the reference to the tmp and says there is nothing there. I have the ability to redrag the file once it is running and it will work fine.
Why am I losing the file on play??
[SerializeField] TMP_Text score;
int points;
// Start is called before the first frame update
void Awake()
{
points = 0;
score = GetComponent<TMP_Text>();
}
// Update is called once per frame
void Update()
{
score.SetText(points.ToString());
}
public void AddToScore(int score)
{
points += score;
}
This is a very simple script. The file I am atttaching has no script or anythin to it. It is just a basic text mesh pro object.

In awake you reassign score. The problem is you do a GetComponent which only searches the current GameObject. Since UIController does not contain a TMP_Text component it return null and so you lose the reference. If you just remove that line (score = GetComponent<TMP_Text>();) it will fix your issue

Related

Creating multiple buttons using input field in Unity

I just want to ask how can I multiple the buttons by using the input field? Like for example, I typed 100 in the input field and then the buttons will become 100. Please bear in mind that I'm new in Unity. Thank you!
First you need to define what button you want to instantiate, on the UI Canvas or a 3D world button.
public class TestingScript : MonoBehaviour{
// the button to create
public GameObject button;
}
You need to create a prefab or assign an existing button in the world for the script to use as a template when creating them. Next you need to create the input field itself and assign the reference to it through code or in the inspector view, here I am going to have it assigned in the inspector.
// assigned in inspector view
public TMP_InputField inputField;
It should look like this in the component view
Now where you call the function is your choosing, I am doing it through a unity button on which I have the script attached
The method here would look something like this
public void CreateButtons()
{
// here we assume the input is always an integer, otherwise you would create a try catch clause
int amount = int.Parse(inputField.text);
// using world 0 position here, you would need to define where you want them yourself
Vector2 pos = new Vector2(0, 0);
for (int i = 0; i < amount; i++)
{
// the loop will execute the amount of times read from input field
Instantiate(button, pos, Quaternion.identity);
pos.x += 0.5f;
}
}
Note I am using TextMeshPro elements here but the standard unity ones would work too.

Unity - Prefab with Sub-Elements Expansion Button Missing in Project Panel

I have been following along with a course. In this course a GameObject called "Path (0)" is added, this GameObject then has three sub-GameObjects ("Waypoint (0/1/2)"). In the tutorial, the guy drags the parent GameObject "Path (0)" into a folder called Paths in the Project panel to create a prefab. This prefab is shown with a handle to expand it. He then expands this prefab to see the sub-elements which can be dragged into the Inspector, as shown below (expand button highlighted with red box)
When I perform these operations, the Project panel does not have an expand button on the "Path" prefab (see below)
Why does my prefab object in the Project panel not have these expansion buttons?
Basically, what he does is he creates a script component with enemy prefab.(attached bellow). and the childobject "waypoints" are marks in scene where enemy will move. I uploaded a part of tutorial on youtube, which i will delete once the problem is solved. if youtube dosent delete it. Please help i am half through the tutorial.
https://youtu.be/NGpaHSmktic
public class EnemyPathing : MonoBehaviour {
[SerializeField] List waypoints;
[SerializeField] float moveSpeed = 2f;
int waypointIndex = 0;
void Start()
{
transform.position = waypoints[waypointIndex].transform.position;
}
// Update is called once per frame
void Update()
{
Move();
}
private void Move()
{
if (waypointIndex < -waypoints.Count - 1)
{
var targetPosition = waypoints[waypointIndex].transform.position; // this is where we go to
var movementThisFrame = moveSpeed * Time.deltaTime; // this is how fast we want to go to
transform.position = Vector2.MoveTowards(transform.position, targetPosition, movementThisFrame);
if (transform.position == targetPosition)
{
waypointIndex++;
}
}
else
{
Destroy(gameObject);
}
}
It must be because you don't have the same unity version.
Simply double click on Path0 and it will open it. In the Hierarchy tab, you will see the asset and its elements.
If you drag back Path0 to the scene, its children will appear too.
It's because you're not supposed to drag a child asset away from its parent.
I don't know how it is used in your tutorial, but if needed, you can make a child prefab too by dragging it to the folder (After double clicking on Path0).
Edit :
I don't really know what you can do to have the exact same situation, but here is another way :
-create a tag 'waypoint' and set this tag for Waypoint0, Waypoint1 and Waypoint2 (in your asset, or before creating it).
-In the Start method of your EnemyPathing.cs add this :
this.waypoints = new List<Transform>();
foreach(GameObject g in GameObject.FindGameObjectsWithTag("waypoint"))
{
waypoints.Add(g.transform);
}
So, it will automatically add your waypoints, even if you have more or less than 3 in your scene.

Unity, Volume Slider Problem When Changing Scence

im making a game that have a empty game object for audio source (music) and the script for that music, and i also have a volume slider in diffrent object .
The Script :
float musicVolume = 1f;
private void Update()
{
mainMusic.volume = musicVolume;
}
// Slider will Trigger This
public void SetVolume(float volume)
{
musicVolume = volume;
}
i use that way because it's simple and easy since i will only use 1 music.
With that i can control my music volume correctly, but the problem is when i go to another scence and go back, the slider seems don't do anything so my music volume won't cahange.
So how to i fix it?
Sorry for my bad english. Thanks...
First Of All you can remove Volume initialize From Update Method
Your Problem
When Set Volume From Slider It's Okk set Success Like 0.5f
But After Call Update Methos So Your Volume Set 1f from musicVolume variable
Solution
remove Volume initialize From Update Method
My guess is that the object having the AudioSource is destroied as soon as a new scene is loaded.
Go with this in its script in order to avoid its deallocation when you change the scene:
void Awake () {
DontDestroyOnLoad(this);
}
As a side note, your Update could be avoided because setting the volume at each frame is not optimal.
why not simply
public void SetVolume(float volume)
{
mainMusic.volume = volume;
}
without the Update in between? Do the work only when it is needed!
To your question: it sounds like you are using DontDestroyOnLoad on the mainMusic and loosing the reference due to destroying the duplicate after loading the scene. You should get an exception about that!
However, simply search for the AudioSource in your script like
private void Start()
{
mainMusic = FindObjectOfType<AudioSource>();
}
public void SetVolume(...){ ... }
or if there are multiple AudioSources in your Scene give the main source an explicit type like e.g.
public MainAudioSource : AudioSource
{
// Does nothing but now you can explicitely search for it
}
and then in the other script do
private void Start()
{
mainMusic = FindObjectOfType<MainAudioSource>();
}

Unity3D: Setting AudioSource volume dynamically using AnimationCurve

Newcomer to Unity here. For this project, I am reading in an outside AnimationCurve, and attempting to use it to adjust the volume of my GameObject every frame in the Update function. I have found documentation on how to access the volume of my AudioSource GameObject component (this is working), but I can't figure out how to use my evaluated curve to update the volume.
Screencap with imported AnimationCurve and evaluated values
My cs script is included below. Sorry if it's a bit opaque. This is for a neuroscience experiment, so I need to carefully control the animation curves. It reads in times and values (stored in currentCurveData) used to add keyframes to the new AnimationCurve (curveThisTrl) in the SetAnimationFrames() function.
The key part is in Update(). The initial tone.volume is correct, so I know it's reading that property from the GameObject. I can also see the correct curve values coming through in the Debug Log every frame, so I know the curve evaluation is working. It's just not changing the volume property of the GameObject as I want it to.
Hopefully this is enough information to spot a problem, but if not I can try to provide a test AnimationCurve for reproducibility. Thanks in advance for any help.
public class AnimationControl : MonoBehaviour {
private DataController dataControllerRef;
private CurveDataSingleTrial currentCurveData;
private float initTime;
public AnimationCurve curveThisTrl;
AudioSource tone;
void Awake()
{
initTime = Time.time;
}
// Use this for initialization
void Start ()
{
// Get references to key objects in scene
dataControllerRef = FindObjectOfType<DataController>(); // Has values from JSON
tone = GetComponent<AudioSource>();
Debug.Log(tone.volume);
// query the DataController for the current curve data
currentCurveData = dataControllerRef.GetCurrentCurveData();
SetAnimationFrames();
}
void SetAnimationFrames()
{
int numKeyFrames = currentCurveData.keyframeTimes.Length;
for (int c = 0; c < numKeyFrames; c++)
{
curveThisTrl.AddKey(currentCurveData.keyframeTimes[c], currentCurveData.keyframeVals[c]);
}
}
// Update is called once per frame
void Update ()
{
float currTime = Time.time - initTime;
tone.volume = curveThisTrl.Evaluate(currTime);
Debug.Log(tone.volume);
}
}

Why the IK controller is not exist in the ThirdPersonController Animator component in the Inspector?

I'm trying to follow the instructions in the unity documents how to use Inverse Kinematics in this page:
Inverse Kinematics
But i don't have the IK Animator Controller when i select Controller for the Animator.
I tried adding the script now. But the hand the right hand is folded to the other side. It's not like it's holding the flash light: The script is attached to the ThirdPersonController. And i dragged to the script in the Inspector to the rightHandObj the EthanRightHand and to the lookObj i dragged the Flashlight.
But the hand seems to be wrong way.
This is the script i'm using now the IKControl:
using UnityEngine;
using System;
using System.Collections;
[RequireComponent(typeof(Animator))]
public class IKControl : MonoBehaviour
{
protected Animator animator;
public bool ikActive = false;
public Transform rightHandObj = null;
public Transform lookObj = null;
void Start()
{
animator = GetComponent<Animator>();
}
//a callback for calculating IK
void OnAnimatorIK()
{
if (animator)
{
//if the IK is active, set the position and rotation directly to the goal.
if (ikActive)
{
// Set the look target position, if one has been assigned
if (lookObj != null)
{
animator.SetLookAtWeight(1);
animator.SetLookAtPosition(lookObj.position);
}
// Set the right hand target position and rotation, if one has been assigned
if (rightHandObj != null)
{
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1);
animator.SetIKPosition(AvatarIKGoal.RightHand, rightHandObj.position);
animator.SetIKRotation(AvatarIKGoal.RightHand, rightHandObj.rotation);
}
}
//if the IK is not active, set the position and rotation of the hand and head back to the original position
else
{
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 0);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 0);
animator.SetLookAtWeight(0);
}
}
}
}
Add an empty game object to the flashlight and target that instead of the flashlight object itself. Hit play and then fiddle with the placement of the empty object until it is where you want it. Then just turn the flashlight into a prefab, stop play mode and make sure the flashlight in the scene matches the prefab (you can just use revert to do that if needed).
Now it would be doing exactly what you want every time. You could even have multiple prefabs with the empty object positioned differently to allow characters with larger or smaller hands to hold it convincingly.