Hey there everyone my name is Tz,
Recently I got a little stuck on something, this “something” is converting this tutorial
from JavaScript to C#.
I have almost successfully completed this, I now have no errors, etc, but when the helicopter adds torque (in c#) it won’t stop, even when I’m not moving my mouse.
If this is any consolation, here’s the code.
using UnityEngine;
using System.Collections;
public class HairyCopter : MonoBehaviour {
public GameObject main_Rotor_GameObject; // gameObject to be animated
public GameObject tail_Rotor_GameObject; // gameObject to be animated
public float max_Rotor_Force = 22241.1081f; // newtons
private float max_Rotor_Velocity = 7200; // degrees per second
private float rotor_Velocity = 0.0f; // value between 0 and 1
private float rotor_Rotation = 0.0f; // degrees... used for animating rotors
public float max_tail_Rotor_Force = 15000.0f; // newtons
public float max_Tail_Rotor_Velocity = 2200.0f; // degrees per second
private float tail_Rotor_Velocity = 0.0f; // value between 0 and 1
private float tail_Rotor_Rotation = 0.0f; // degrees... used for animating rotors
public float forward_Rotor_Torque_Multiplier = 0.5f; // multiplier for control input
public float sideways_Rotor_Torque_Multiplier = 0.5f; // multiplier for control input
private bool main_Rotor_Active = true; // boolean for determining if a prop is active
private bool tail_Rotor_Active = true; // boolean for determining if a prop is active
public Vector3 MyPos;
public Quaternion MyRot;
Vector3 torqueValue;
//Vector3 controlTorque;
// Forces are applied in a fixed update function so that they are consistent no matter what the frame rate of the game is. This is
// important to keeping the helicopter stable in the air. If the forces were applied at an inconsistent rate, the helicopter would behave
// irregularly
float MouseY;
float MouseX;
float H;
float V;
// Forces are applied in a fixed update function so that they are consistent no matter what the frame rate of the game is. This is
// important to keeping the helicopter stable in the air. If the forces were applied at an inconsistent rate, the helicopter would behave
// irregularly.
[RPC]
void SendMouseInputs(float Mx,float My)
{
//controlTorque = Vector3(My * forward_Rotor_Torque_Multiplier,1.0, -Mx * sideways_Rotor_Torque_Multiplier);
MouseY = My * (PlayerPrefs.GetFloat("YSensVeh") /3);
MouseX = -Mx * (PlayerPrefs.GetFloat("XSensVeh") / 8);
}
void FixedUpdate () {
// First we must compute the torque values that are applied to the helicopter by the propellers. The "Control Torque" is used to simulate
// the variable angle of the blades on a helicopter and the "Torque Value" is the final sum of the torque from the engine attached to the
// main rotor, and the torque applied by the tail rotor.
//if(Input.GetAxis("Mouse Y") != 0 || Input.GetAxis("Mouse X") != 0)
// controlTorque = new Vector3(Input.GetAxis("Mouse Y") * forward_Rotor_Torque_Multiplier, 1.0f, -Input.GetAxis("Mouse X") * sideways_Rotor_Torque_Multiplier);
if (GetComponent<VehicleController>().Driver == MultiplayerManager.instance.MyPlayer)
{
if (Input.GetAxis("Mouse X") != 0 || Input.GetAxis("Mouse Y") != 0)
{
if (Network.isServer)
SendMouseInputs(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
else
networkView.RPC("SendMouseInputs", RPCMode.Server, Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
}
}
Debug.Log("mousex is "+MouseX);
Debug.Log("mousey is "+MouseY);
if (Network.isClient)
return;
Vector3 controlTorque = new Vector3(MouseY, 1.0f, MouseX);
/// networkView.RPC("SyncControlTorque", RPCMode.Server, Input.GetAxis("Mouse Y") * forward_Rotor_Torque_Multiplier, -Input.GetAxis("Mouse X") * sideways_Rotor_Torque_Multiplier);
// Now check if the main rotor is active, if it is, then add it's torque to the "Torque Value", and apply the forces to the body of the
// helicopter.
//if ( main_Rotor_Active == true ) {
torqueValue += (controlTorque * max_Rotor_Force * rotor_Velocity);
// Now the force of the prop is applied. The main rotor applies a force direclty related to the maximum force of the prop and the
// prop velocity (a value from 0 to 1)
rigidbody.AddRelativeForce( Vector3.up * max_Rotor_Force * rotor_Velocity );
// This is simple code to help stabilize the helicopter. It essentially pulls the body back towards neutral when it is at an angle to
// prevent it from tumbling in the air.
if ( Vector3.Angle( Vector3.up, transform.up ) > 110 ) {
transform.rotation = Quaternion.Slerp( transform.rotation, Quaternion.Euler( 0, transform.rotation.eulerAngles.y, 0 ), Time.deltaTime * rotor_Velocity * 2 );
//transform.eulerAngles = Vector3.Lerp(transform.eulerAngles,new Vector3(0,transform.rotation.eulerAngles.y,0),Time.deltaTime * rotor_Velocity * 2);
}
//}
// Now we check to make sure the tail rotor is active, if it is, we add it's force to the "Torque Value"
//if ( tail_Rotor_Active == true ) {
torqueValue -= (Vector3.up * max_tail_Rotor_Force * tail_Rotor_Velocity);
//torqueValue.y -= max_tail_Rotor_Force * tail_Rotor_Velocity;
///}
// And finally, apply the torques to the body of the helicopter.
rigidbody.AddRelativeTorque( torqueValue);
}
[RPC]
void SendKeyInputs(float h,float v){
H = h;
V = v;
}
void Update () {
// This line simply changes the pitch of the attached audio emitter to match the speed of the main rotor.
if (networkView.isMine)
{
MyPos = transform.position;
MyRot = transform.rotation;
}
else
{
transform.position = Vector3.Lerp(transform.position, MyPos, Time.deltaTime * 5);
transform.rotation = Quaternion.Lerp(transform.rotation, MyRot, Time.deltaTime * 5);
}
if (GetComponent<VehicleController>().Driver == MultiplayerManager.instance.MyPlayer)
{
if (Input.GetAxis("Vertical") != 0.0f || Input.GetAxis("Horizontal") != 0.0f)
{
if (Network.isServer)
SendKeyInputs(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
else
networkView.RPC("SendKeyInputs", RPCMode.Server, Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
}
}
if (Network.isClient)
return;
audio.pitch = rotor_Velocity;
// Now we animate the rotors, simply by setting their rotation to an increasing value multiplied by the helicopter body's rotation.
//if ( main_Rotor_Active == true ) {
main_Rotor_GameObject.transform.rotation = transform.rotation * Quaternion.Euler( 0, rotor_Rotation, 0);
//}
//if ( tail_Rotor_Active == true ) {
tail_Rotor_GameObject.transform.rotation = transform.rotation * Quaternion.Euler( -tail_Rotor_Rotation, 0, 0 );
//}
// this just increases the rotation value for the animation of the rotors.
rotor_Rotation += max_Rotor_Velocity * rotor_Velocity * Time.deltaTime;
tail_Rotor_Rotation += max_Tail_Rotor_Velocity * rotor_Velocity * Time.deltaTime;
// here we find the velocity required to keep the helicopter level. With the rotors at this speed, all forces on the helicopter cancel
// each other out and it should hover as-is.
float hover_Rotor_Velocity = (rigidbody.mass * Mathf.Abs( Physics.gravity.y ) / max_Rotor_Force);
float hover_Tail_Rotor_Velocity = (max_Rotor_Force * rotor_Velocity) / max_tail_Rotor_Force;
// Now check if the player is applying any throttle control input, if they are, then increase or decrease the prop velocity, otherwise,
// slowly LERP the rotor speed to the neutral speed. The tail rotor velocity is set to the neutral speed plus the player horizontal input.
// Because the torque applied by the main rotor is directly proportional to the velocity of the main rotor and the velocity of the tail rotor,
// so when the tail rotor velocity decreases, the body of the helicopter rotates.
if ( V != 0.0f ) {
rotor_Velocity += V * 0.001f;
}else{
rotor_Velocity = Mathf.Lerp( rotor_Velocity, hover_Rotor_Velocity, Time.deltaTime * Time.deltaTime * 5 );
}
tail_Rotor_Velocity = hover_Tail_Rotor_Velocity - H;
//Debug.Log(tail_Rotor_Velocity);
// now we set velocity limits. The multiplier for rotor velocity is fixed to a range between 0 and 1. You can limit the tail rotor velocity
// too, but this makes it more difficult to balance the helicopter variables so that the helicopter will fly well.
if ( rotor_Velocity > 1.0f ) {
rotor_Velocity = 1.0f;
}else if ( rotor_Velocity < 0.0f ) {
rotor_Velocity = 0.0f;
}
}
void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
{
if (stream.isWriting)
{
MyPos = transform.position;
MyRot = transform.rotation;
stream.Serialize(ref MyPos);
stream.Serialize(ref MyRot);
stream.Serialize(ref rotor_Velocity);
stream.Serialize(ref rotor_Rotation);
stream.Serialize(ref tail_Rotor_Rotation);
}
else
{
stream.Serialize(ref MyPos);
stream.Serialize(ref MyRot);
stream.Serialize(ref rotor_Velocity);
stream.Serialize(ref rotor_Rotation);
stream.Serialize(ref tail_Rotor_Rotation);
transform.position = Vector3.Lerp(transform.position, MyPos, Time.deltaTime * 5);
transform.rotation = Quaternion.Lerp(transform.rotation, MyRot, Time.deltaTime * 5);
}
}
}
PS : The code is for authoritative server, so if I’ve done anything wrong there, that will be greatly appreciated too :).
Does the code from the tutorial work?
– Dave-CarlileYes, it does
– joeybubble1Are you trying to convert it to learn C# or to learn Unity? Doing both at once is a bit daunting, unless you know C++ or Java already (the syntaxes are very close).
– Wazneither, i know enough about c# and unity, I'm doing it because the rest of my game is in c#. so i converted it to make my life easier in the long run
– joeybubble1I assume this your issue is happening because the code on line 102 is happening every frame of FixedUpdate. The torque must be non-zero every frame if you're getting the result you do. There are some if statements that are comment out in that scope, as well, perhaps those are conditions that nullify your torque / zero-out your torque?
– hoy_smallfry