Jump to content
Site Stability Read more... ×
  • Advertisement

ferrous

Member
  • Content Count

    1134
  • Joined

  • Last visited

Community Reputation

6164 Excellent

1 Follower

About ferrous

  • Rank
    Contributor

Personal Information

  • Role
    Writer
  • Interests
    Education

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Haha, now you have me curious what your scene is like, as you shouldn't be getting amazing improvements if you're mostly 'ground' objects. Unless CompareTag is slow. (Which I suspect it might be) I'm also not sure what kind of spatial partitioning that unity does. So it might be trying to check against more objects than you think. Anyway, Physics layers and Layer masking are great ways to improve performance. So definitely make sure you understand them.
  2. If your scene has 100 objects, your original code will raycast against those 100 objects, looking for hits, copy the results of up to twenty objects that hit the ray, and then you check if those 20 objects are ground objects. By using layermasking, we first filter out the 100 objects for ground objects. (Of which there might be only one!) Then we do a ray test on those objects. So even if there is no GC difference, there should be a order of magnitude difference, especially as object count and complexity goes up. That and we eliminate the tag check as well. I don't recall if the single hit method returns the closest or not, it would be pretty garbage if it didn't, but I wouldn't be surprised if it didn't, or if it generated more GC that the non-alloc. Though I wonder how much it of a difference there is if compiling to their il2cpp code.
  3. I mean that you no longer need to check for multiple hits, therefore don't need to use the Physics.Raycast that returns multiple hits, which should theoretically invoke much less garbage collection than yours,since no array is required.
  4. You could drastically speed up your raycast/ground check by using a layermask. If you only checked for objects on the ground layer, there would be no need to compare tags. In fact, at that point, depending on your game, you might not even need the raycastnonalloc, if for example your terrain was a single Terrain.
  5. ferrous

    Missile Command, Part 1

    Okay, I lied, life happened, not sure I'll make the January deadline (not that it matters all that much, I suppose). I'll still try to get a link and some screenshots up when I get a chance.
  6. ferrous

    Missile Command, Part 1

    I'll follow this up with a more verbose post with pictures and links, but I figured I'd start things out. So for the Missile Command challenge, I decided I wanted to try a couple of different things: 1. Drunk Missiles. You know, those weird randomly spinning anime missiles from Macross / Robotech. 2. Use UniRX some more. Now, the first one ended up causing lots of other design decisions. First, to really be able to see a drunk missile, I needed 3D, and to best show off the drunken 3d spin, I decided I need a more cinematically placed camera. My early experiments with 3d spinning in Unity, I quickly learned that the default spin rate on rigidbodies are incredibly low, and hidden behind a code only property. I also found any tweaks to missile speed would have them behave rather unpredictably, either doing a very slow spin in a circle, or that my missiles were too drunk, and easily spun off and then back on camera again, It's not much fun to lose a city because a missile spins off camera and then back on camera at the last moment. Now, I knew going in, that I might have to scratch missiles as an interception mechanic, as drunk missiles would be too hard to intercept. But it turns out, even doing a hit-scan raycast was difficult. Partly because clicking directly on a spinning drunk missile is hard, and partly because, the spirit of missile command is causing chain reaction explosions to catch other missiles. To that end, I wanted to be able to click anywhere. and setup an explosion in advance. But... how do you do that in 3d? I ended up setting down a 3d Plane in between the missile spawner and the ctiyscape. But my drunken missiles were so drunk, that there was little guarantee of them even meeting that plane at all. The solution was to drop my first implementation of drunken missiles. The second implementation is even hackier than what I had, but also much more predictable. It involves two game objects. One is the anchor, that is invisible, and moves right along that 3d Plane, and moves straight towards it's target (A city or a tower). The second is the missile, which is attached to the anchor via a hingejoint. It spins around the anchor via the motor property on the hingejoint. I then play with the anchor distance as it gets closer to the target, eventually becoming zero, so that it converges with the anchor. Viola -- Drunken missiles stay on the 3dplane, but still spin. They're still a right pain to click on, but one can still click the plane, and set up chain explosions. Now, for the interception mechanic, I probably could've settled for straight up clicking, but I've decided to try implementing lasers. My first thought was a big beam, but I've since rethought it. I've still got the three towers, and shoot from the nearest tower. That makes planning where the beam will come from kind of a pain. So now I'm thinking of the more traditional star wars blaster laser. It'll still be fairly thick, to help catch drunken missiles in their spin. (I'm still tempted to have all shots come from a single point, and the towers to just act like ammo containers.) And I'm digging UniRX for it's event handling. I'm not utilizing it to it's fullest though, and hacky code abounds as I don't have as much time as I'd like to polish things, but oh well.
  7. ferrous

    Learning UniRX

    Here's another set of slides that I found helpful as well, I think I like it better for it's small concrete examples. http://slides.com/sammegidov/unirx#/
  8. ferrous

    Learning UniRX

    So, it's been a while, but @Eck posted, and it inspired me to do a post as well. I tend to code in spurts when something interests me. And I get distracted easily. I came across UniRX as a possible solution to the doldrums of writing event systems and doing SendMessage all over the place, and then decided to learn it by just starting a game from scratch with it. And using it everywhere, even if it might not be the best fit, just to see what it could do. What's UniRX? Well here's a small presentation, and here's a link to the github. So, the game? A simple RTS, a much simpler version of that turn based tank game that's forever on the back burner. So the short version Mech Commander, with Tanks instead of Mechs. Let's start with our PlayerController, it basically does two things, unit selection, and sending commands to the selected unit. public class PlayerController : MonoBehaviour { UniRx.ReactiveProperty<Controllable> _selectedObject = new ReactiveProperty<Controllable>(); void Start () { LeftClicks().Subscribe(p => { RaycastHit hit; GameObject go = null; if (Physics.Raycast(Camera.main.ScreenPointToRay(p), out hit, unitLayer)) { go = hit.collider.gameObject; } _selectedObject.Value = go ? go.GetComponent<Controllable>() : null; }); RightClicks().Where(_=> _selectedObject.Value != null).Subscribe(p => { RaycastHit hit; GameObject go = null; if (Physics.Raycast(Camera.main.ScreenPointToRay(p), out hit)) { go = hit.collider.gameObject; if(go.GetComponent<Targetable>()) { if (go != this.gameObject) { _selectedObject.Value.CommandStream.SetValueAndForceNotify(new AttackTargetCommand(go)); } } else { _selectedObject.Value.CommandStream.SetValueAndForceNotify(new MoveToCommand(hit.point)); } } }); } public IObservable<Vector3> LeftClicks() { return Observable.EveryUpdate() .Where(_ => Input.GetMouseButtonDown(0)) .Select(_ => Input.mousePosition); } public IObservable<Vector3> RightClicks() { return Observable.EveryUpdate() .Where(_ => Input.GetMouseButtonDown(1)) .Select(_ => Input.mousePosition); } Okay, so on a basic level, each unit has a Controllable component that is fairly simple, it's basically just a ICommand queue public class Controllable : MonoBehaviour { public UniRx.ReactiveProperty<ICommand> CommandStream = new ReactiveProperty<ICommand>(); public IObservable<GameObject> LatestTarget() { return CommandStream.Where(cmd => cmd is AttackTargetCommand).Select(cmd => ((AttackTargetCommand)cmd).Target); } } And then we have optional components that look at that command stream, like Moveable and Turret. Lets look at Moveable first, it's really simple at the moment. [RequireComponent(typeof(NavMeshAgent))] public class Moveable : MonoBehaviour { void Start () { MoveCommandStream().Subscribe(p => this.GetComponent<NavMeshAgent>().SetDestination(p));} private IObservable<Vector3> MoveCommandStream() { return this.GetComponentInParent<Controllable>().CommandStream.Where(cmd => cmd is MoveToCommand).Select(cmd => ((MoveToCommand)cmd).Position); } } The turret is a little more complicated public class Turret : MonoBehaviour { IDisposable rotateTowardsSubscription = null; void Start () { this.GetComponentInParent<Controllable>().LatestTarget().Subscribe(target => { if(rotateTowardsSubscription != null) { // Stop any rotations rotateTowardsSubscription.Dispose(); rotateTowardsSubscription = null; } if (target != null) { rotateTowardsSubscription = EveryUpdate().Subscribe(x => { if (target != null) { RotateTowards(target.transform.position); } }); } }); } private RotateTowards() {} // not showing this for brevity's sake, and I'm cheesing it at the moment anyway } And then the WeaponMount which does the actual firing, with a bunch of non-uniRX code culled out, I abstracted it out into separate components for multi gun turrets, or fixed guns, etc, as well as code clarity. public class WeaponMount : MonoBehaviour { [SerializeField] float ReloadTime = 1.0f; BoolReactiveProperty weaponLoaded = new BoolReactiveProperty(false); IDisposable fireSubscription = null; void Start () { this.GetComponentInParent<Controllable>().LatestTarget().Subscribe(target => { // Stop any fire subs if (fireSubscription != null) { fireSubscription.Dispose(); fireSubscription = null; } if (target != null) { fireSubscription = EveryUpdate().Where(_ => CanFireAtTarget(target)).Subscribe(_ => Fire()); } }); weaponLoaded.Where(loaded => loaded == false).Delay(TimeSpan.FromSeconds(ReloadTime)).Subscribe(_ => weaponLoaded.Value = true); } What's interesting is just how different the code looks from standard Unity code, even coroutine code (Though that's perhaps the closest). I started to really enjoy it once I managed to wrap my mind around it, it's a rather small amount of code to select, move and attack with units. Once I'd built up my vocabulary of Linq-like syntax, it makes it very easy to see whats going on and do things like the weapon reload, which is just one line. Minor quibble: I do wish Unity had greater C# version support, I want to do foo?.Dispose() and be done with it already.
  9. ferrous

    Missile Command Challenge

    Ah, I never played Car Wars tabletop, though I did buy a copy of the rules not too long ago. It looks like it might be a little complicated to implement as a video game, should be a good challenge to make it flow well. I need to get off my duff and at least post about my adventures learning UniRX. Maybe I'll try pivoting over and doing Missile Command using it. EDIT: Also Grrrr, not being able to shoot through your own explosions was annoying! =)
  10. ferrous

    Missile Command Challenge

    Nice, I have to admit, I was tempted to get in on this challenge, as someone who played lots of Missile Command, but got distracted by the holidays. Whats this about a Car Wars prototype? I feel like we need a blog post about it =)
  11. Hello ferrous i hope you answer my message, I think you know quite a bit about 2D RPGS and stuff and I wanted to ask for your help because i'm working on a small project just for fun and I want to make my sprite able to change different armors and weapons but I literally have no idea about how to do that, Please help

    1. Drezor

      Drezor

      I forgot to mention that i'm using Java

  12. ferrous

    The Incredible Lightness of Being An Ark Developer

    So the real question with regards to the long hours, is did you feel they were required to keep your job?  Would you have been fired if you didn't work them?  Would you have been unable to complete your work?Did you feel more effective working those long hours?  
  13. ferrous

    Sony C#/.NET Component Set Analysis

    The tool was correct to flag it, but I thought the author's interpretation on how to fix it was incorrect.
  14. ferrous

    Sony C#/.NET Component Set Analysis

    I suspect your intepretation of the following code is incorrect: while (res.Operation.Status != DispatcherOperationStatus.Completed || res.Operation.Status == DispatcherOperationStatus.Aborted) { Thread.Sleep(50); } I get the impression that the author of the code wanted to run that loop until either the operation was completed or aborted.  So it should be something like: while (!(res.Operation.Status == DispatcherOperationStatus.Completed || res.Operation.Status == DispatcherOperationStatus.Aborted)) { Thread.Sleep(50); } (that's a ugly loop, there's probably a more clear way to format it)
  15. Hah, I had no idea you were a DigiPenner too.
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!