I am trying to make a machine gun’s 8 barrels rotate while it is shooting so that the top barrel always shoots. I have managed to make the barrels rotate using Transform.Rotate in the FireOneShot function. However, I am not sure how to create a rotation of 360/8 = 45 degrees so that the intermediate stages are rendered. The time interval between shots is much larger than deltatime, so doing a rotation of 45 degrees once for every shot would not look nice. What is the best way to do this?
Would using update be best, so that there would be a rotation of 45*(deltatime/fireInterval) degrees for fireInterval/deltatime updates for each shot?
I’d use a coroutine, and Quaternion.Lerp to rotate between two specific angles:
var rotateSpeed = 5.0;
var degreesToRotate = 45.0;
function Start () {
while (true) {
if (Input.GetButton("Fire1")) {
yield Fire();
}
yield;
}
}
function Fire () {
// Instantiate bullet here
// Rotate barrel
var t = 0.0;
var startRotation = transform.rotation;
var endRotation = transform.rotation * Quaternion.Euler(Vector3.forward * degreesToRotate);
while (t < 1.0) {
t += Time.deltaTime * rotateSpeed;
transform.rotation = Quaternion.Lerp(startRotation, endRotation, t);
yield;
}
}
–Eric
Usually a function’s parameters are explained in documentation for anything, but not in Unity’s documentation. It is very annoying that the third parameter is not explained in Unity - Scripting API: Quaternion.Lerp so I do not understand what lerp is used for. The parameter’s name is t, suggesting that it is time, but in the example, Time.time * speed is passed in, suggesting that it is an angle.
Could you explain why your method is better than the one that I suggested.
The use of Time.time in the examples provided in the documentation is misleading (at best), and has caused much confusion.
The t argument is the parametric interpolation value, and is used to ‘mix’ the two input values proportionally. For example, a value of 0 will cause the value returned to be the same as that of the first argument, a value of 1 will cause the value returned to be the same as that of the second argument, and values in the range [0, 1] will cause a value somewhere between (for some definition of ‘between’) the two input values to be returned. (Some of Unity’s ‘lerp’ functions clamp the t parameter to the range [0, 1], but I couldn’t say without checking whether they all do that.)
It’s explained in Mathf.Lerp. All the Lerp functions work the same way…if t is 0.0 you get the first parameter, if it’s 1.0 you get the second parameter, everything else is a proportional mix. See also here.
It’s far simpler to control what happens and to make it end exactly where you want it to. My code just advances t from 0.0 to 1.0, so the rotation goes from the first angle to the last. Multiplying by speed just affects how fast it goes from 0 to 1.
–Eric
I modified your Fire function and put it into the FireOneShot function, which is called many times by my Fire function:
var rotateSpeed = 45/fireInterval;
var t = 0.0;
var startRotation = barrels.rotation;
var endRotation = barrels.rotation * Quaternion.Euler(Vector3.forward * 45);
while (t < 1.0) {
t += Time.deltaTime * rotateSpeed;
barrels.rotation = Quaternion.Lerp(startRotation, endRotation, t);
No rotation is produced. What is the problem?
Can you post the script in its entirety? (Or at least the relevant portions.)
Meanwhile:
Probably this:
The code Eric posted functions as a unit, and in a specific way; simply copying part of it and pasting it into your code somewhere is unlikely to produce the desired result. (It’ll be easier to tell what’s going on though once we can see your code in its entirety.)