Please help me understand how to add the concept of getData to the code, I don't understand it very well(
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.PlayerLoop;
public class Control : MonoBehaviour
{
public float speed = 5f; // скорость персонажа
void Update()
{
if (Microphone.IsRecording(null))
{ // проверяем, записывает ли микрофон что-либо
float[] volumeData = new float[256]; // создаем массив для хранения данных о громкости
int offset = Microphone.GetPosition(null) - volumeData.Length; // узнаем, сколько элементов нужно "пропустить"
Microphone.GetDeviceCaps(null, out int minFreq, out int maxFreq); // узнаем, какие частоты может "выдавать" микрофон
if (minFreq < maxFreq)
{ // если minFreq < maxFreq, то...
Microphone.GetData(volumeData, offset); // ...заполняем volumeData
float sum = 0f; // суммируем "уровни" (для удобства)
for (int i = 0; i < volumeData.Length; i++)
{
sum += Mathf.Abs(volumeData[i]); // Mathf.Abs - "модуль" (abs - absolute value)
}
float averageVolume = sum / 256f; // 256 - "длина" volumeData
transform.Translate(Vector3.forward * averageVolume * speed * Time.deltaTime); // "двигаем" персонаж
}
}
}
}
If you understand or know how to solve this problem, then write and I will count your question!
And yes, I know it's easy for you, but unfortunately I don't understand everything yet, thank you in advance
Related
So I wrote a day-night cycle script the other day and I have the sun/moon cycle working (its a really rough script, not perfect yet) but one of the other things I wanted to do was to be able to calculate the current time inside the game working off of that day/night cycle.
I have a ticker that is working so far but it is not scaling correctly to the percentage of the day.
Can anyone help me out with this because I think this is beyond my skillset with maths right now.
Basically I just want to solve the current time of day as relative to the % we are moving through the day/night cycle.
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class DayNightCycle : MonoBehaviour
{
public static DayNightCycle instance;
public Light sun, moon;
public float secondsInFullDay = 3600f;
[Range(0, 1)]
public float currentTimeOfDay = 0f;
[HideInInspector]
public float timeMultiplier = 1f;
float sunInitialIntensity;
public Camera mainCam;
public Material skyboxDay, skyBoxNight;
public float gameTime;
public float fSeconds;
public int totalSeconds, iSeconds, minutes, hours, days;
public int currentSecond, currentMinute, currentHour, currentDay;
public float previousTime;
private void Awake()
{
instance = this;
}
// Start is called before the first frame update
void Start()
{
sunInitialIntensity = sun.intensity;
}
// Update is called once per frame
void Update()
{
UpdateSun();
currentTimeOfDay += (Time.deltaTime / secondsInFullDay) * timeMultiplier;
if (currentTimeOfDay >= 1)
{
currentTimeOfDay = 0;
}
gameTime += Time.deltaTime;
// seconds / total seconds = percentage
// percentage * seconds = total seconds
// seconds = total seconds * percentage
totalSeconds = (int)gameTime;
fSeconds = (secondsInFullDay * currentTimeOfDay);
currentSecond = (int)fSeconds;
if (currentSecond >= 60)
IncrementMinutes();
if (currentMinute >= 60)
IncrementHours();
if (currentHour >= 24)
IncrementDays();
previousTime = (int)gameTime;
}
void UpdateSun()
{
sun.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
moon.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
float intensityMultiplier = 1f;
float moonIntensityMult = 0.025f;
if (currentTimeOfDay <= 0.23f || currentTimeOfDay >= 0.75f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = 0f;
moonIntensityMult = 0.025f;
}
else if (currentTimeOfDay <= 0.25f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = Mathf.Clamp01((currentTimeOfDay - 0.23f) * (1 / 0.02f));
moonIntensityMult = 0f;
}
else if (currentTimeOfDay >= 0.73f)
{
RenderSettings.skybox = skyboxDay;
intensityMultiplier = Mathf.Clamp01(1 - ((currentTimeOfDay - 0.73f) * (1 / 0.02f)));
moonIntensityMult = 0f;
}
sun.intensity = sunInitialIntensity * intensityMultiplier;
moon.intensity = moonIntensityMult;
}
public float GetTimeOfDayInSeconds
{
get { return currentTimeOfDay; }
set { return; }
}
void IncrementMinutes()
{
currentMinute++;
currentSecond = 0;
}
void IncrementHours()
{
currentHour++;
currentSecond = 0;
currentMinute = 0;
}
void IncrementDays()
{
currentDay++;
currentSecond = 0;
currentMinute = 0;
currentHour = 0;
}
}
I think keeping track of second, minute hour and increment each separtedly is not the right approach. You need to now the scale or proprotion factor between your game time and the real time, and handle the one time variable at once.
Find this trial function to obtain the sacaled time I think you need.
using System;
using UnityEngine;
public class DayNightCycle : MonoBehaviour {
// This is public to check with manual input if the obtained time is the one we expect.
// In the real method, this should not exist and should be calculated with the elapsed time of the game,
// commented belowin the getGameTime(int secodsDayDurationInGame) method
public double elapsedRealTime;
float startingGameTime;
DateTime startingGameDate;
private void Start() {
startingGameTime = Time.time;
startingGameDate = DateTime.Now; // choose the starting date you like
}
private float secondsOfARealDay = 24 * 60 * 60;
DateTime getGameTime(int secodsDayDurationInGame) {
float scaledElapsedSecondInGame = secondsOfARealDay / secodsDayDurationInGame; // second equivalent in your game
//float elapsedRealTime = Time.time - startingGameTime; // uncomment to calculate with elapsed real time.
DateTime gateDateTime = startingGameDate.AddSeconds(elapsedRealTime * scaledElapsedSecondInGame);
return gateDateTime;
}
void OnMouseDown() { // this makes the cube clickable
Debug.LogError(getGameTime(3600).ToString());
}
}
You can try it making a cube clickable to print the output when you update the elapsed time in the public variable.
It is for 3600 second day in your game, but if you whant another game day duration you can just make that variabel puclic and try.
Important to have a collider, if not, cube wont be clickable. However It is added by default when you add the primitive right click in the scene -> 3D Object -> Cube.
You can check for example that if you add 3600 to the elapsed time public variable, and you click the cube you obtain tomorrows date in the console.
When you check the function works according to your needs you can uncomment the line //float elapsedRealTime = Time.time - startingGameTime; to use the real time elapsed or the one you wish for the date calculation.
Okay so I got it to where it is correctly synched now with the day/night cycle I just need to clean this code up quite a bit. Note: The way I'm increasing days will start to fail if you use an exceptionally long in game day I think. The boolean might work but it might also give you a new day before the end of the current day. I was testing this on a 3600 second long day.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class DayNightCycle : MonoBehaviour
{
public static DayNightCycle instance;
public Light sun, moon;
public float secondsInFullDay = 3600f;
[Range(0, 1)]
public float currentTimeOfDay = 0f;
[HideInInspector]
public float timeMultiplier = 1f;
float sunInitialIntensity;
public Material skyboxDay, skyBoxNight;
public double elapsedRealTime;
public float secondsPerDayMultiplier;
[SerializeField]
private float speedOfGameSecond, speedOfGameMinute, speedOfGameHour, speedOfGameDay;
[SerializeField]
private float currentGameSecond, currentGameMinute, currentGameHour, currentGameDay;
private bool stopIncrementingDay;
private void Awake()
{
instance = this;
}
// Start is called before the first frame update
void Start()
{
speedOfGameSecond = secondsInFullDay / 24 / 60 / 60;
speedOfGameMinute = secondsInFullDay / 24 / 60;
speedOfGameHour = secondsInFullDay / 24;
speedOfGameDay = secondsInFullDay;
sunInitialIntensity = sun.intensity;
}
// Update is called once per frame
void Update()
{
UpdateSun();
currentTimeOfDay += (Time.deltaTime / secondsInFullDay) * timeMultiplier;
if (currentTimeOfDay >= 1)
{
currentTimeOfDay = 0;
}
secondsPerDayMultiplier = currentTimeOfDay * secondsInFullDay;
// seconds / total seconds = percentage
// percentage * seconds = total seconds
// seconds = total seconds * percentage
currentGameSecond = secondsPerDayMultiplier / speedOfGameSecond;
currentGameMinute = secondsPerDayMultiplier / speedOfGameMinute;
currentGameHour = secondsPerDayMultiplier / speedOfGameHour;
if(!stopIncrementingDay && currentGameHour >= 23.999)
{
IncrementDay();
stopIncrementingDay = true;
} else if(currentGameHour <= 23.999)
{
stopIncrementingDay = false;
}
elapsedRealTime += Time.deltaTime;
previousTime = Time.deltaTime;
}
void UpdateSun()
{
sun.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
moon.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
float intensityMultiplier = 1f;
float moonIntensityMult = 0.025f;
if (currentTimeOfDay <= 0.23f || currentTimeOfDay >= 0.85f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = 0f;
moonIntensityMult = 0.025f;
}
else if (currentTimeOfDay <= 0.25f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = Mathf.Clamp01((currentTimeOfDay - 0.23f) * (1 / 0.02f));
moonIntensityMult = 0f;
}
else if (currentTimeOfDay >= 0.83f)
{
RenderSettings.skybox = skyboxDay;
intensityMultiplier = Mathf.Clamp01(1 - ((currentTimeOfDay - 0.83f) * (1 / 0.02f)));
moonIntensityMult = 0f;
}
sun.intensity = sunInitialIntensity * intensityMultiplier;
moon.intensity = moonIntensityMult;
}
public float GetTimeOfDayPercent
{
get { return currentTimeOfDay; }
set { return; }
}
public float GetSecondsPerDay()
{
return secondsInFullDay;
}
private void IncrementDay()
{
currentGameSecond = 0;
currentGameMinute = 0;
currentGameHour = 0;
currentGameDay++;
}
public void GetTimeOfDay()
{
// now to work on this
}
}
I want my shots to follow a specific pattern (I also need the arc and gap between the shots to be adjustable). Right now I've got my shooting script down but the shots go in a straight line which is not what I want (don't want a straight line now but I'll need it later when designing other weapons).
Here's a screenshot with example of said saidpatters:
I don't know much about quaternions and angles so all I tried is modifying the angles after x time and the velocity after x time but none worked (it might be the solution but I have 0 clue how to use angles in unity so I couldn't get it to work).
Another thing please provide an explanation along with your answer because I want to learn why something works the way it does so I don't have to ask again later.
Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class Player_Shooting : MonoBehaviour
{
[SerializeField]
private Transform shootingPoint;
[SerializeField]
private GameObject shot; //this is what I'm shooting, shot also has a script but all it does is apply velocity upwards and do damage to enemy if it hits
private bool shootAgain = true;
private int dexterity = Player_Stats.GetDexterity();
private int numberofshots = 2; //amount of shots
private int shotGap = 5; //how many degrees between the shots
void Update()
{
Vector3 mousepos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 direction = new Vector2(mousepos.x - transform.position.x, mousepos.y - transform.position.y);
transform.up = direction;
if (Input.GetButton("Fire1") && shootAgain == true)
{
shootAgain = false;
StartCoroutine(RateOfFire(dexterity));
}
}
private void Shoot()
{
Vector3 temp = transform.rotation.eulerAngles;
Quaternion angle = Quaternion.Euler(temp.x, temp.y, temp.z);
for (int i = 0; i < numberofshots; i++)
{
int multiplier = i + 1;
if (numberofshots % 2 == 1)
{
Instantiate(shot, shootingPoint.position, angle);
if (i % 2 == 0)
{
temp.z -= shotGap * multiplier;
angle = Quaternion.Euler(temp.x, temp.y, temp.z);
}
else
{
temp.z += shotGap * multiplier;
angle = Quaternion.Euler(temp.x, temp.y, temp.z);
}
}
else if (numberofshots % 2 == 0)
{
if (i % 2 == 0)
{
temp.z -= shotGap * multiplier;
angle = Quaternion.Euler(temp.x, temp.y, temp.z);
}
else
{
temp.z += shotGap * multiplier;
angle = Quaternion.Euler(temp.x, temp.y, temp.z);
}
Instantiate(shot, shootingPoint.position, angle);
}
}
}
IEnumerator RateOfFire(int dex)
{
Shoot();
float time = dex / 75;
time *= 6.5f;
time += 1.5f;
yield return new WaitForSeconds(1 / time);
shootAgain = true;
}
}
This is what i came up with after a few hours.
it can be improved upon for your needs but it works and with less code.
i used a separate script on another gameObject to Instantiate the projectiles. The bullet script is attached to a sprite with a trail
it should be easy to manipulate the firing sequence from there.
comments explain what most things do.
i added a bool function to fire in opposing angles.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class bullet : MonoBehaviour{
public float turnLength = 0.5f; // how long it turns for 0.0+
public float turnSpeed = 5f; // how fast the projectile turns 0.0+
public float anglePauseTime = 0.2f; // Optional wave form variable. coupled with high turnrate + curve speed = higher frequency sine wave.
public float shotAngle = -12f; // the angle the shot is taken as an offset (usually nagative value) 0- or turnspeed*2.25 for straight shots
public float projectileSpeed = 50; // obvious
public bool opositeAngles = false;
// Start is called before the first frame update
void Start(){
if(opositeAngles){
transform.Rotate(0, 0, -shotAngle);
}
else{
transform.Rotate(0, 0, shotAngle);
}
StartCoroutine(WaveForm(turnLength, turnSpeed, anglePauseTime, opositeAngles));
}
// Update is called once per frame
void Update(){
transform.position += transform.right * Time.deltaTime * projectileSpeed;
}
IEnumerator WaveForm(float seconds, float aglSpeed, float pause, bool reverse){
// multiplier correlates to waitForSeconds(seconds)
// faster update time = smoother curves for fast projectiles
// less cycles = shorter Corutine time.
//10, 0.1 100cycles/second (shallow waves, jagged on higher frequency waves, doesnt last long)
//10, 0.05 200cycles/second (probably best)
//100, 0.02 500cycles/second (smooth curves all around. requires smaller adjustment numbers)
// i had to up it for the waveform to last longer.
float newSeconds = seconds * 10;
for (int i = 0; i < newSeconds; i++) {
for (int j = 0; j < newSeconds; j++) {
yield return new WaitForSeconds(0.05f); // controls update time in fractions of a second.
if(reverse){
transform.Rotate(0, 0, -aglSpeed, Space.Self);
}
else {
transform.Rotate(0, 0, aglSpeed, Space.Self);
}
}
yield return new WaitForSeconds(pause);
aglSpeed = -aglSpeed;
}
}
}
Example image
I am making an AR experience where I would like to use a phone's compass to direct a player toward true north, but I am having problems with smoothing the compass readings on Android devices. The code I have experimented with so far logs a certain number of readings into a queue, copies the queue into a list and then once the list is full it takes the average of all the readings. From here I would like to scale the reading between -1 & 1, where 0 represents South. Then I want this data to be used to rotate a compass image on the GUI layer.
The data is nowhere near as smooth as I'd like it to be, but here is the code I have so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CompassSlider : MonoBehaviour
{
public float reading;
public Queue<float> data;
private float[] dataList;
public int maxData = 100;
public int count;
public float sum, average;
public float dampening = 0.1f;
public float rotationToNorth;
// Use this for initialization
void Start()
{
data = new Queue<float>();
dataList = new float[maxData];
}
// Update is called once per frame
void Update()
{
Input.location.Start();
Input.compass.enabled = true;
count = data.Count;
if (data.Count > 0)
{
data.CopyTo(dataList, 0);
}
if (data.Count == maxData)
{
for (int i = 0; i < data.Count; i++)
{
sum += dataList[i];
}
if (Mathf.Abs(dataList[maxData - 1]) > 0)
{
average = sum / maxData;
sum = 0;
data.Clear();
dataList = new float[maxData];
}
}
if (data.Count >= maxData)
{
data.Dequeue();
}
reading = Mathf.Round(Input.compass.trueHeading);
data.Enqueue(reading);
if (count == maxData) {
rotationToNorth = average / 180;
rotationToNorth = (Mathf.Round(rotationToNorth * 10)) / 10;
rotationToNorth = rotationToNorth - 1;
}
}
}
What I want to do is instantiate a prefab in a circle, but over time. So that one prefab will appear and the others will appear over time. Should I be using a coroutine to achieve this effect?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fire_Circle : MonoBehaviour
{
public GameObject prefab;
public int numberOfObjects = 20;
public float radius = 5f;
public float height;
void Start()
{
for (int i = 0; i < numberOfObjects; i++)
{
float angle = i * Mathf.PI * 2 / numberOfObjects;
Vector3 pos = new Vector3(Mathf.Cos(angle), height / radius,
Mathf.Sin(angle)) * radius;
Instantiate(prefab, pos, prefab.transform.rotation );
}
}
}
Coroutines are certainly a nice option:
void Start()
{
StartCoroutine(SpawnObjs());
}
IEnumerator SpawnObjs()
{
for (int i = 0; i < numberOfObjects; i++)
{
float angle = i * Mathf.PI * 2 / numberOfObjects;
Vector3 pos = new Vector3(Mathf.Cos(angle), height / radius,
Mathf.Sin(angle)) * radius;
Instantiate(prefab, pos, prefab.transform.rotation );
yield return new WaitForSeconds(.8f);
}
}
This is code for Unity 3D Game Engine...
I try to monitor sound decibels using this source scripts but why i am getting Negative Decibel ?
In theory, sound from Normal Conversation will result 60db and even silent room will make 10-20dB...
any idea ?
Result of Decibel Calculation :
and below are source code :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VR_SoundMonitor : MonoBehaviour
{
public float DecibleValue;
public float RmsValue;
public float PitchValue;
private AudioSource audioSourceObject;
private float[] _spectrum;
private float[] _samples;
private float _fSample;
const int QSamples = 1024;
const float RefValue = 0.1f;
const float Threshold = 0.02f;
void Start ()
{
audioSourceObject = GetComponent<AudioSource> ();
InitVariable ();
InitMicrophone ();
}
//Nyalakan Microphone
private void InitMicrophone()
{
audioSourceObject.clip = Microphone.Start ("SoundMonitoring", false, 60, 44100);
while (!(Microphone.GetPosition(null) > 0)) { }
audioSourceObject.Play();
}
private void InitVariable()
{
_samples = new float[QSamples]; //use constanta (3 below)
_spectrum = new float[QSamples];
_fSample = AudioSettings.outputSampleRate;
}
void Update ()
{
CalculateAnalyzeSound (audioSourceObject);
Debug.Log ("Decibels="+DecibleValue+" ## RmsVal="+RmsValue);
}
public void CalculateAnalyzeSound(AudioSource audio)
{
float _RmsValue;
float _DbValue;
float _PitchValue;
audio.GetOutputData(_samples, 0);
int i = 0;
float sum = 0;
for (i = 0; i < QSamples; i++)
{
sum += _samples[i] * _samples[i]; // sum squared samples
}
_RmsValue = Mathf.Sqrt(sum / QSamples); // rms = square root of average
_DbValue = 20 * Mathf.Log10(_RmsValue / RefValue); // calculate dB
if (_DbValue < -160) _DbValue = -160; // clamp it to -160dB min
RmsValue = _RmsValue;
DecibleValue = _DbValue;
}
}
What's Wrong ? Any idea, please let me know....