unity-game-enginetextmeshpro

How to display text in Unity game


I inherited by my ex collegue a Unity game. Now I need to implement this behaviour. The game consist in a car drive by user using Logitech steering.

Now I need to show a Text every X minute in a part of the screen like "What level of anxiety do you have ? " Ad the user should to set a value from 0 to 9 using the Logitech steering but I really don't know where to start. This is my manager class:

using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
namespace DrivingTest
{
    // Braking test Manager
    public class BtManager : BaseTestManger
    {
        // Public variables
        public BreakCar breakCar;
        public float minBrakeThreshold = 0.2f;
        internal int vehicalSpeed;
        internal int noOfEvents;
        internal float durationOfTest;

        // Private variables
        private IRDSPlayerControls playerControlCar;
        protected int xSpeed;
        protected int ySpeed;
        private float brakeEventStartTime;
        private float brakeEventDifferenceTime;
        private SafetyDistanceCheck safetyDistanceCheck;
        protected float totalSafetyDistance;
        protected int totalSafetyDistanceCount;

        private List<float> averageEventReactionTime = new List<float>();

        #region Init
        // Use this for initialization
        public override void Start()
        {
            base.Start();
            playerControlCar = car.GetComponent<IRDSPlayerControls>();
            safetyDistanceCheck = car.GetComponent<SafetyDistanceCheck>();
        }

        public override void OnEnable()
        {
            base.OnEnable();
            BreakCar.BrakeStart += BrakeCarEvent;
            BreakCar.BrakeEventEnd += CallTestOver;
        }

        public override void OnDisable()
        {
            base.OnDisable();
            BreakCar.BrakeStart -= BrakeCarEvent;
            BreakCar.BrakeEventEnd -= CallTestOver;
        }

        protected override void SetUpCar()
        {
            car.AddComponent<SelfDriving>();
        }

        #endregion


        /// <summary>
        /// Calls the main Test over method.
        /// </summary>
        private void CallTestOver()
        {
            GameManager.Instance.Testover();
        }


        protected override void OnSceneLoaded(eTESTS test)
        {
            UiManager.Instance.UpdateInstructions(Constants.BT_INSTRUCTION);
        }

        protected override void GetApiParams()
        {
            NextTestOutput nextTestOutput = GameManager.Instance.currentTest;

            if (nextTestOutput.content != null && nextTestOutput.content.Count > 0)
            {
                foreach (var item in nextTestOutput.content[0].listInputParameter)
                {
                    switch ((ePARAMETERS)item.id)
                    {
                        case ePARAMETERS.X_SPEED:
                            xSpeed = System.Convert.ToInt32(item.Value);
                            break;

                        case ePARAMETERS.Y_SPEED:
                            ySpeed = System.Convert.ToInt32(item.Value);
                            break;

                        case ePARAMETERS.SPEED_OF_VEHICLE:
                            vehicalSpeed = System.Convert.ToInt32(item.Value);
                            break;

                        case ePARAMETERS.NUMBER_OF_EVENTS:
                            noOfEvents = System.Convert.ToInt32(item.Value);
                            break;

                        case ePARAMETERS.DURATION_OF_TEST:
                            durationOfTest = float.Parse(item.Value) * 60; //converting minutes into seconds
                            break;

                    }
                }

                SetupBrakeCar();
            }
        }

        protected virtual void SetupBrakeCar()
        {
            DOTween.Clear();
            durationOfTest = noOfEvents * Random.Range(10,20);  // The random value is the time between two consecutive tests.
            breakCar.SetInitalParams(new BrakeCarInit
            {
                carMaxSpeed = vehicalSpeed * 0.95f,
                durationOfTest = durationOfTest,
                noOfEvents = noOfEvents,
                xSpeed = xSpeed,
                ySpeed = ySpeed
            });
            breakCar.distanceCheck = true;
        }

        protected override void SubmitRestultToServer()
        {
            SubmitTest submitTest = new SubmitTest
            {
                outputParameters = new List<SaveOutputParameter>
                {
                    new SaveOutputParameter
                    {
                        id = (int)ePARAMETERS.OUT_REACTION_TIME,
                        value = ((int)(GetEventReactionTimeAvg () * Constants.FLOAT_TO_INT_MULTIPLAYER)).ToString()
                    },
                    new SaveOutputParameter
                    {
                        id = (int)ePARAMETERS.OUT_AVG_RT,
                        value = GetReactionResult().ToString()
                    }
                }
            };
            WebService.Instance.SendRequest(Constants.API_URL_FIRST_SAVE_TEST_RESULT, JsonUtility.ToJson(submitTest), SubmitedResultCallback);
        }

        protected override void ShowResult()
        {
            UiManager.Instance.UpdateStats(
               (
                "1. " + Constants.EVENT_REACTION + (GetEventReactionTimeAvg() * Constants.FLOAT_TO_INT_MULTIPLAYER).ToString("0.00") + "\n" +
                "2. " + Constants.REACTION_TIME + reactionTest.GetReactionTimeAvg().ToString("0.00")
               ));
        }

        public void LateUpdate()
        {
            //Debug.Log("TH  " + .Car.ThrottleInput1 + " TH " + playerControlCar.Car.ThrottleInput + " brake " + playerControlCar.Car.Brake + " brake IP " + playerControlCar.Car.BrakeInput);
            //Debug.Log("BrakeCarEvent "+ brakeEventStartTime + " Player car " + playerControlCar.ThrottleInput1 + " minBrakeThreshold " + minBrakeThreshold);

            if (brakeEventStartTime > 0 && playerControlCar.Car.ThrottleInput1 > minBrakeThreshold)
            {
                brakeEventDifferenceTime = Time.time - brakeEventStartTime;
                Debug.Log("Brake event diff " + brakeEventDifferenceTime);
                Debug.Log("Throttle " + playerControlCar.Car.ThrottleInput1);
                averageEventReactionTime.Add(brakeEventDifferenceTime);
                brakeEventStartTime = 0;
                safetyDistanceCheck.GetSafetyDistance(SafetyDistance);
            }
        }

        private void SafetyDistance(float obj)
        {
            totalSafetyDistance += obj;
            ++totalSafetyDistanceCount;
        }


        /// <summary>
        /// Records the time when the car ahead starts braking
        /// </summary>
        protected void BrakeCarEvent()
        {
            brakeEventStartTime = Time.time;
            Debug.Log("BrakeCarEvent ");

        }

        
        /// <summary>
        /// calculates the average time taken to react  
        /// </summary>
        public float GetEventReactionTimeAvg()
        {
            float avg = 0;
            foreach (var item in averageEventReactionTime)
            {
                avg += item;
            }//noofevents
            return avg / (float)averageEventReactionTime.Count;
        }

    }
}

EDIT

I create new class FearTest:

 using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace DrivingTest
{
    public class FearTest : MonoBehaviour
    {
        //public GameObject redDot;
        public TextMeshPro textAnsia2;
        public TextMesh textAnsia3;
     
        public int shouldEvaluateTest = 0; // 0 - false, 1 - true
        public int secondsInterval;
        public int secondsToDisaply;
        public int radiusR1;
        public int radiusR2;
        public int reactionTestDuration;
        public int maxDots;
        public float dotRadius = 1;
        private float endTime;
        private float dotDisaplyAtTime;
        private List<float> dotDisplayReactTime = new List<float>();
        private int missedSignals;
        private int currentDotsCount;
        private bool isReactionAlreadyGiven;
        public bool ShouldEvaluateTest
        {
            get
            {
                return shouldEvaluateTest != 0;
            }
        }
     
        void OnEnable()
        {
            GameManager.TestSceneLoaded += OnSceneLoaded;
        }
        private void OnDisable()
        {
            GameManager.TestSceneLoaded -= OnSceneLoaded;
        }
        #region Scene Loaded
        private void OnSceneLoaded(eTESTS test)
        {
            if (SceneManager.GetActiveScene().name != test.ToString())
                return;
            Reset();
            GetApiParams();
        }
        #endregion
        private void GetApiParams()
        {
#if UNITY_EDITOR
            if (!GameManager.Instance)
            {
                Init();
                return;
            }
#endif
            Debug.Log("called rt");
            NextTestOutput nextTestOutput = GameManager.Instance.currentTest;
            if (nextTestOutput.content != null && nextTestOutput.content.Count > 0)
            {
                foreach (var item in nextTestOutput.content[0].listInputParameter)
                {
                    switch ((ePARAMETERS)item.id)
                    {
                        case ePARAMETERS.RT_ENABLE:
                            shouldEvaluateTest = System.Convert.ToInt32(item.Value);
                            break;
                        case ePARAMETERS.RT_DURATION:
                            reactionTestDuration = System.Convert.ToInt32(item.Value);
                            break;
                        case ePARAMETERS.RED_DOT_FREQ:
                            secondsInterval = System.Convert.ToInt32(item.Value);
                            break;
                        case ePARAMETERS.RED_DOT_MAX_COUNT:
                            maxDots = System.Convert.ToInt32(item.Value);
                            break;
                        case ePARAMETERS.RED_DOT_RADIUS_R1:
                            radiusR1 = System.Convert.ToInt32(item.Value);
                            break;
                        case ePARAMETERS.RED_DOT_RADIUS_R2:
                            radiusR2 = System.Convert.ToInt32(item.Value);
                            break;
                        case ePARAMETERS.RED_DOT_SIZE:
                            dotRadius = float.Parse(item.Value)/10f;
                            break;
                        case ePARAMETERS.RED_DOT_TIME:
                            secondsToDisaply = System.Convert.ToInt32(item.Value);
                            break;
                    }
                }
                Debug.Log("called rt "+ shouldEvaluateTest);
                /*if (ShouldEvaluateTest)
                {
                    Init();
                }*/
                Init();//dopo bisogna sistemare il shoudl evaluatetest
            }
        }
        Coroutine displayCoroutine;
        public void Init()
        {
            endTime = Time.time + reactionTestDuration + 10;
            SetRedDotSize();
            displayCoroutine = StartCoroutine(RedDotDisplay());
        }
        private IEnumerator RedDotDisplay()
        {
            yield return new WaitForSeconds(2);
            while (true)
            {
                SetRandomDotPosition();
                RedDot(true);
                isReactionAlreadyGiven = false;
                dotDisaplyAtTime = Time.time;
                currentDotsCount++;
                yield return new WaitForSeconds(secondsToDisaply);
                if(!isReactionAlreadyGiven)
                {
                    missedSignals++;
                }
                RedDot(false);
                if ((reactionTestDuration > 0 && endTime <= Time.time) || (maxDots > 0 && currentDotsCount >= maxDots))
                    break;
                float waitTime = secondsInterval - secondsToDisaply;
                yield return new WaitForSeconds(waitTime);
            }
        }
        private void Update()
        {
            if (!ShouldEvaluateTest)
                return;
            if (!isReactionAlreadyGiven && /*redDot.activeSelf &&*/ (LogitechGSDK.LogiIsConnected(0) && LogitechGSDK.LogiButtonIsPressed(0, 23)))
            {
                isReactionAlreadyGiven = true;
                float reactionTime = Time.time - dotDisaplyAtTime;
                Debug.Log("Reaction Time RT : " + reactionTime);
                RedDot(false);
                dotDisplayReactTime.Add(reactionTime);
            }
        }
        public double GetReactionTimeAvg()
        {
            double avg = 0;
            foreach (var item in dotDisplayReactTime)
            {
                avg += item;
            }
            //avg / currentDotsCount
            return avg / (float)dotDisplayReactTime.Count;
        }
        public double GetMissedSignals()
        {
            return ((float) missedSignals / (float) currentDotsCount) * 100;
        }
        private void RedDot(bool state)
        {
            //redDot.SetActive(state);
            textAnsia2.SetText("Pippo 2");
         
        }
        private void SetRedDotSize()
        {
            //redDot.transform.localScale *= dotRadius;
            textAnsia2.transform.localScale *= dotRadius;
            textAnsia3.transform.localScale *= dotRadius;
        }
        private void SetRandomDotPosition()
        {
            //redDot.GetComponent<RectTransform>().anchoredPosition = GetRandomPointBetweenTwoCircles(radiusR1, radiusR2)*scale;
            float scale = ((Screen.height*0.9f) / radiusR2) * 0.9f;
            Vector3 pos = GetRandomPointBetweenTwoCircles(radiusR1, radiusR2) * scale;
            Debug.Log("RT temp pos : " + pos);
            pos = new Vector3(500, 500, 0);
            Debug.Log("RT pos : " + pos);
          //  redDot.transform.position = pos;
            Vector3 pos2 = new Vector3(20, 20, 0);
            Debug.Log("text ansia 2 : " + pos2);
            textAnsia2.transform.position = pos2;
            textAnsia3.transform.position = pos;
        }
        #region Getting Red Dot b/w 2 cricles
        /*
         Code from : https://gist.github.com/Ashwinning/89fa09b3aa3de4fd72c946a874b77658
        */
        /// <summary>
        /// Returns a random point in the space between two concentric circles.
        /// </summary>
        /// <param name="minRadius"></param>
        /// <param name="maxRadius"></param>
        /// <returns></returns>
        Vector3 GetRandomPointBetweenTwoCircles(float minRadius, float maxRadius)
        {
            //Get a point on a unit circle (radius = 1) by normalizing a random point inside unit circle.
            Vector3 randomUnitPoint = Random.insideUnitCircle.normalized;
            //Now get a random point between the corresponding points on both the circles
            return GetRandomVector3Between(randomUnitPoint * minRadius, randomUnitPoint * maxRadius);
        }
        /// <summary>
        /// Returns a random vector3 between min and max. (Inclusive)
        /// </summary>
        /// <returns>The <see cref="UnityEngine.Vector3"/>.</returns>
        /// <param name="min">Minimum.</param>
        /// <param name="max">Max.</param>
        Vector3 GetRandomVector3Between(Vector3 min, Vector3 max)
        {
            return min + Random.Range(0, 1) * (max - min);
        }
        #endregion
        #region Reset
        private void Reset()
        {
            if (displayCoroutine != null)
                StopCoroutine(displayCoroutine);
            RedDot(false);
            shouldEvaluateTest = 0;
            reactionTestDuration = 0;
            secondsInterval = 0;
            missedSignals = 0;
            maxDots = 0;
            radiusR1 = 0;
            radiusR2 = 0;
            dotRadius = 1;
            secondsToDisaply = 0;
            endTime = 0;
            dotDisaplyAtTime = 0;
            dotDisplayReactTime.Clear();
            //redDot.transform.localScale = Vector3.one;
            textAnsia2.transform.localScale = Vector3.one;
            textAnsia3.transform.localScale = Vector3.one;
            currentDotsCount = 0;
            isReactionAlreadyGiven = true;
        }
        #endregion
    }
}

When "SetRandomDotPosition" method is called, in my scene I can display in a random position of the screen the RedDot (that is a simple image with a red dot), but I m not able to display my textAnsia2. How can I fixed it ?


Solution

  • I hope this will help you to get started :

    https://vimeo.com/709527359

    the scripts:

    https://i.sstatic.net/ytWKQ.jpg

    I hope that in the video i covered every step that i've made.

    Edit: The only thing is for you to do is to make the input of the Wheel to work on the slider. Try to make a simple script: when the text is enabled then the input from a joystick to work on that . When is disabled switch it back for his purpose .