Tag Archives: C#

C#

S.W.A.P. Missile: Perfect Orbits

Recently while I was tweaking the Swap missiles tracking in my upcoming game S.W.A.P. I encounter a funny little Bug where it would “orbit” its target. I recorded a short video which you can watch below:

I thought I’d briefly share the code that produced this result:

// ... Target Acquisition Ocures up here ...

void RotateTowards(Vector3 target)
{
	Vector3 dirToAvatar = (transform.position - target).normalized;

	// work out angle between us and the target.
	float angle = Vector3.Angle(dirToAvatar, transform.forward);
	float rotAmount = Mathf.Clamp01( maxTrunAmount / angle );	// this prevents us from rotating more them the maximum allowed!!
	Quaternion temp = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(-dirToAvatar), rotAmount);
	rigidbody.MoveRotation(temp);
}

So the goal of this function is to rotate the missile so it faces the target. However the amount it can rotate is capped by maxTrunAmount. The problem was that if you got the distance and angle right the missile would need to rotate more then maxTrunAmount would allow it to. If you got this just right this would result in stable “orbits” where the missile would just keep circling the target.

The final code I ended up using looked like this:

void RotateTowards(Vector3 target)
{
	Vector3 dirToAvatar = transform.position - target;
	float distToAvatarSqr = dirToAvatar.sqrMagnitude;
	dirToAvatar.Normalize();

	// Work out how far we can rotate based on distance to target:
	float t = 1 - (distToAvatarSqr / (trackingDistanceSqr - 2));
	t = Mathf.Clamp01( missileTurningCurve.Evaluate(t) );

	Quaternion newRot = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(-dirToAvatar), t);
	rigidbody.MoveRotation(newRot);
}

Needless to say this actually works quite differently. This time, in addition to tracking the target we also wanted to adjust how far the missile could turn, when it was right at the end of its tracking range, it would turn only a small amount. As it gets closer it can turn faster, When it gets really close it will got straight for the target.

On line 8 we work out how close we are to the target as a percentage (0 being far away, 1 being at the target). Note that we take 2 away from our max tracking distance, this is to take into account that the targets position is in the centre of the avatar and for this number to ever be 1 we must get to a distance of 0. Because of the Targets collider (and the missile’s too) this is impossible, so we have minus 2.

On line 9 we use a curve (which I have expose in the inspector) to transform this range percentage into a rotation percentage. We use the curve because we wanted to have the missile turn in gradually at first but much more sharply as it got closer. The curve looks like this:

SwapMissileTurnCurve
Swap Missile Turn Curve

By eliminating the artificial maxTrunAmount we have allowed the swap missile to (eventually) turn the full required amount to actually hit and eliminated the “orbits”. (of course if I couldn’t fix it we would have ended up with swap Sharks instead, which could have been fun :D).

Actually the single best thing to come out of this was my learning about the AnimationCurve.Evaluate() function. It makes it trivial to expose a curve in the inspector which can be edited by an artist and then use it to control a lerp between two values (colour, position, rotation , whatever). This actually allows me solve one of the most frequent questions I get from an artist when I setup a mechanic that involve a lerp, i.e Can you change it so…? Now I can just tell them: Do it yourself! and that always make me feel good.

Advertisements

The S.W.A.P. Debug Console

 

When we were developing the original Prototype for S.W.A.P. we ran into A LOT of problem, by far the worst of which was encountered on the afternoon the day before our deadline. With more then two players in the game there would be ‘ownership’ issues after a players swaps, i.e. two players would control the same avatar. In the end this bug forced us to rely on a video when pitching the game, instead of a live demo.

One reason why the bug caused such a problem was because we had no way to get debug information from the unity player. We needed a console, one where we could enter commands and receive feedback from the game and we didn’t have one. Continue reading The S.W.A.P. Debug Console

Lambdas: What are they and When to use them!

I’ve always know that Lambdas existed and had some idea as to what they were (inline functions right?); but I never really bothered to learn how to use them (and the few times I came across them i had no idea what I was looking at). It wasn’t until recently, while reading about the new c++11 features, that I finally came to understand what they are and how to use them.  With my more recent discovery that (unlike most new c++11 features) they can be used in Visual Studio 2010 I thought I’d share my new insight.

Because it took me a while to get my head around them I’ve tried to make this explanation as simple as possible so a relative newcomer to c++ can understand them. However I will point out that if you don’t know what function pointers are and how to use them your going to struggle with the lambdas.

Continue reading Lambdas: What are they and When to use them!

To get things started…

To get things started I thought I’d post some information I promised a friend on easy multi-threading techniques in C#/.Net.

First trick is to use the Parrallel Class. This is a new addition in .Net 4.0 that provides version of for and foreach that will automatically split up the loop to run across multiple threads, depending on how many cores the System CPU has and how much load each core is under (this can be controlled too, if need be).

The other is Background Workers. Background workers are best used for slow jobs that might cause the UI to lock up (such as long file IO operations). A Background worker runs whatever task you give it on a separate thread, preventing the UI from locking up and allowing the user to do other thing while they wait for it to complete. The background worker provides a series of events for monitoring its progress.

Hope you find these useful in your future .Net projects.