コード例 #1
0
ファイル: TheKernel.cs プロジェクト: wang-yichun/AnimalStory
    public override void GetContent(IDocumentationBuilder _)
    {
        base.GetContent(_);
        _.Paragraph("The uFrame Kernel is an essential piece of uFrame, it handles loading scenes, systems and services.  " +
                    "The kernel is nothing more than a prefab with these types of components attached to it in an organized manner.");

        _.ImageByUrl("http://i.imgur.com/5Rg2X25.png");

        _.Paragraph("In the image above you can see the scene 'BasicsProjectKernelScene'.  This scene will always always contain the 'BasicsProjectKernel' " +
                    "prefab and any other things that need to live throughout the entire lifecycle of your application.");
        _.Paragraph("Important Note: All SystemLoaders, Services, and SceneLoaders are MonoBehaviours attached their corresponding child game-objects in the kernel prefab.");

        _.Note(
            "Whenever a scene begins, uFrame will ensure that the kernel is loaded, if it hasen't been loaded it will delay " +
            "its loading mechanism until the kernel has been loaded. This is necessary because you might initialize ViewModels, deserialize them...etc so the view should not bind until that data is ready.");

        _.Break();

        _.Title2("Scaffolding The Kernel");
        _.Paragraph("For convenience uFrame 1.6 makes the process of creating the kernel very easy and straightforward.  " +
                    "By pressing the Scaffold/Update Kernel button it will create a scene, and a prefab with all of the types created by the uFrame designer.  " +
                    "You can freely modify the kernel, and updating it will only add anything that is not there.");
        _.Break();

        _.Title2("Boot Order");
        _.ImageByUrl("http://i.imgur.com/L5CC8q8.png");

        _.Title2("The Game Ready Event");
        _.Paragraph("Once the kernal has loaded, it will publish the event 'GameReadyEvent'.  This event ensures that everything is loaded and bindings have properly taken place on views.");
    }
コード例 #2
0
    public override void GetContent(IDocumentationBuilder _)
    {
        base.GetContent(_);
        _.Paragraph("The uFrame Kernel is an essential piece of uFrame, it handles loading scenes, systems and services.  " +
                    "The kernel is nothing more than a prefab with these types of components attached to it in an organized manner.");



        _.ImageByUrl("http://i.imgur.com/5Rg2X25.png");

        _.Paragraph("In the image above you can see the scene 'BasicsProjectKernelScene'.  This scene will always always contain the 'BasicsProjectKernel' " +
                    "prefab and any other things that need to live throughout the entire lifecycle of your application.");
        _.Paragraph("Important Note: All SystemLoaders, Services, and SceneLoaders are MonoBehaviours attached their corresponding child game-objects in the kernel prefab.");

        _.Note(
            "Whenever a scene begins, uFrame will ensure that the kernel is loaded, if it hasen't been loaded it will delay " +
            "its loading mechanism until the kernel has been loaded. This is necessary because you might initialize ViewModels, deserialize them...etc so the view should not bind until that data is ready.");

        _.Break();

        _.Title2("Scaffolding The Kernel");
        _.Paragraph("For convenience uFrame 1.6 makes the process of creating the kernel very easy and straightforward.  " +
                    "By pressing the Scaffold/Update Kernel button it will create a scene, and a prefab with all of the types created by the uFrame designer.  " +
                    "You can freely modify the kernel, and updating it will only add anything that is not there.");
        _.Break();

        _.Title2("Boot Order");
        _.ImageByUrl("http://i.imgur.com/L5CC8q8.png");


        _.Title2("The Game Ready Event");
        _.Paragraph("Once the kernal has loaded, it will publish the event 'GameReadyEvent'.  This event ensures that everything is loaded and bindings have properly taken place on views.");
    }
コード例 #3
0
    protected override void Ending(IDocumentationBuilder _, InteractiveTutorial tutorial)
    {
        _.Paragraph("Now run the game, select the PlayerView gameobject, and type 'Hello World' into the Name field, then press the reset button.  You should also see the console log each change to the property 'Name'");
        _.ImageByUrl("http://i.imgur.com/zrg6r7q.png");

        _.AlsoSeePages(typeof(LoadingAndUnloadingScenes), typeof(CreatingServices));
    }
コード例 #4
0
 public void EnsureCode(IDocumentationBuilder _, DiagramNode codeFor, string description, string imageUrl, string filenameSearch, string codeSearch)
 {
     _.ShowTutorialStep(new TutorialStep(description,
                                         () => EnsureCodeInEditableFile(codeFor, filenameSearch, codeSearch)),
                        b =>
     {
         _.Paragraph(string.Format("Right-Click on the Node and choose Open->{0}", filenameSearch));
         _.ImageByUrl(imageUrl);
     });
 }
コード例 #5
0
 public override void GetContent(IDocumentationBuilder _)
 {
     base.GetContent(_);
     _.ImageByUrl("http://i.imgur.com/2G5Amgx.png");
     _.Paragraph("ViewComponents can be used for a wide variety of things, and are meant to provide a further level of extensibility to Views.  They are derived from MonoBehaviour, and require a View in order to function.  A ViewComponent will bind to the same ViewModel instance to which its corresponding View is bound.  In essence, they are extremely simplistic, offering these things:");
     _.Paragraph(" - Access to a particular View to which it is bound ");
     _.Paragraph("   - Access to that specific ViewModel instance");
     _.Paragraph(" - Matching execute methods for the corresponding View's commands");
     _.Paragraph(" - Awake, Bind, and Unbind methods ");
     _.Paragraph("   - These can be used to implement manual bindings where desired, among other things");
     _.Break();
     _.Paragraph("While entirely optional, there are a lot of creative uses for ViewComponents, including interchangeable behaviours, toggleable logic, and even extending logical ownership for a View.");
     _.Break();
     _.Paragraph("For example, we'll outline a scenario where you wish to have a system that detects hit damage to specific player body parts in an FPS game, in order to have damage multipliers.  In the example diagram below, we have separated out ViewComponents for each type of body part.");
     _.ImageByUrl("http://i.imgur.com/wNxFcQt.png");
     _.Paragraph("On the Player GameObject, we would attach the PlayerView.  Assuming that we have a rigged character model parented to that Player GameObject, we would want to set up Colliders on the joint references of each of the corresponding body parts, similar to the screenshot below:");
     _.ImageByUrl("http://i.imgur.com/GuwVQzf.png");
     _.Paragraph("We can either add ViewComponents at runtime, or assign them directly to each Collider individually:");
     _.ImageByUrl("http://i.imgur.com/RX8hZeY.png");
     _.Paragraph("Once this is done, we simply need to add a short piece of code to each ViewComponent to detect collisions and execute TakeDamage, something like:");
     _.ShowGist("2c2c6ca621f91280b693","PlayerArmComponent.cs");
     _.Paragraph("So now with similar code on all of our body part GameObjects, they will each provide separate collision checks for individual body parts.  If a body part is hit by a bullet GameObject with a BulletView on it, the damage of that BulletViewModel instance will be passed, along with the type of body part hit, to the TakeDamage command on the PlayerController.");
 }
コード例 #6
0
 public override void GetContent(IDocumentationBuilder _)
 {
     base.GetContent(_);
     _.ImageByUrl("http://i.imgur.com/2G5Amgx.png");
     _.Paragraph("ViewComponents can be used for a wide variety of things, and are meant to provide a further level of extensibility to Views.  They are derived from MonoBehaviour, and require a View in order to function.  A ViewComponent will bind to the same ViewModel instance to which its corresponding View is bound.  In essence, they are extremely simplistic, offering these things:");
     _.Paragraph(" - Access to a particular View to which it is bound ");
     _.Paragraph("   - Access to that specific ViewModel instance");
     _.Paragraph(" - Matching execute methods for the corresponding View's commands");
     _.Paragraph(" - Awake, Bind, and Unbind methods ");
     _.Paragraph("   - These can be used to implement manual bindings where desired, among other things");
     _.Break();
     _.Paragraph("While entirely optional, there are a lot of creative uses for ViewComponents, including interchangeable behaviours, toggleable logic, and even extending logical ownership for a View.");
     _.Break();
     _.Paragraph("For example, we'll outline a scenario where you wish to have a system that detects hit damage to specific player body parts in an FPS game, in order to have damage multipliers.  In the example diagram below, we have separated out ViewComponents for each type of body part.");
     _.ImageByUrl("http://i.imgur.com/wNxFcQt.png");
     _.Paragraph("On the Player GameObject, we would attach the PlayerView.  Assuming that we have a rigged character model parented to that Player GameObject, we would want to set up Colliders on the joint references of each of the corresponding body parts, similar to the screenshot below:");
     _.ImageByUrl("http://i.imgur.com/GuwVQzf.png");
     _.Paragraph("We can either add ViewComponents at runtime, or assign them directly to each Collider individually:");
     _.ImageByUrl("http://i.imgur.com/RX8hZeY.png");
     _.Paragraph("Once this is done, we simply need to add a short piece of code to each ViewComponent to detect collisions and execute TakeDamage, something like:");
     _.ShowGist("2c2c6ca621f91280b693", "PlayerArmComponent.cs");
     _.Paragraph("So now with similar code on all of our body part GameObjects, they will each provide separate collision checks for individual body parts.  If a body part is hit by a bullet GameObject with a BulletView on it, the damage of that BulletViewModel instance will be passed, along with the type of body part hit, to the TakeDamage command on the PlayerController.");
 }
コード例 #7
0
    public override void GetContent(IDocumentationBuilder _)
    {
        base.GetContent(_);
        _.Title2("What is it?");
        _.Paragraph("Controllers dictate the rules of your game and, like ViewModels, they do not inherit from Unity's Monobehaviour.  As they only handle logic, there only ever needs to be one Controller for each type of ViewModel.  For example, when a PlayerViewModel performs the PickupItem command, the PlayerController would simply need to know which PlayerViewModel to execute that command logic on, and the logic remains the same whether there are 4 players or one.");

        _.Paragraph(" A controller is designed to implement the data-driven logic and rules behind an element " +
                    "and could be considered just a \"group\" of commands for a view-model. " +
                    "The Designer has enough information about an element to implement most of the controller itself " +
                    "In most instances, you only need to apply the logic and rules to each method.  ");

        _.Break();



        _.Title2("Best Practices");
        _.Paragraph("When implementing controllers, think of the element as its own little section of your world, " +
                    "if you want your element to interact or be visible to the entire world, publish events as " +
                    "necessary in your command controller methods.");
        _.Paragraph("To understand this idea a bit more, take a look at the following diagram.");
        _.ImageByUrl("http://i.imgur.com/KbPL9bw.png");
        _.Paragraph("So in the diagram above, on the EnemyHit command handler, we publish the command as 'global' event.  This means that services can be your general connection layer that make various elements work together.");
        _.Title3("But why should I do this?");
        _.Paragraph("Imagine you create a Player element, if it lives entirely on its own (no dependencies on other controllers, services..etc), you can re-use the element in another game and implement services to connect them together.");
        _.Break();
        _.Break();

        _.Title2("The Setup Method");
        _.Paragraph("The setup method is an implementation of the ISystemService interface, this means that all controllers are ultimately services, they do not derive from monobehaviour.  This means you can easily listen to any kind of event on a controller, as well as publish them.");
        _.Title3("Important Note");
        _.Paragraph("You must be careful when listening to events in controllers that use inheritance. For instance, if you have an elementA controller, and a derived elementB controller, and in the setup method you are listening to event 'C', then beth element A and element B will be listening to the same event.  In some cases this may be wanted behaviour, but its important to understand.");
        _.Break();
        _.Break();
        _.Title2("The Initialize Method");
        _.Paragraph("The initialize Method in a controller can be used to initialize an Element's ViewModel (similar to how it might be initialized in the inspector of a View). It is a great place to subscribe to 'Scene Properties'.");
        _.Title2("Command Handlers");
        _.Paragraph("Every command that is outlined on an element, in the Element Designer, will have a corresponding method in a controller (assuming the diagram is saved).  ");
        _.Paragraph("There are a few things to notice when looking at the code example below:");
        _.Paragraph(" - The \"FPSWeaponController\" is derived from \"FPSWeaponControllerBase\", which is generated by the designer.");
        _.Paragraph(" - All of these methods are overrides, because the base class has implemented an empty \"virtual method\" for each command.");
        _.Paragraph(" - The reload method has an IEnumerator result type, because is it is marked as a yield command (indicated by the yellow marker).  This can be achieved by right-clicking on a command and checking \"Is Yield Command\". It is used for simulating a co-routine.");
        _.Paragraph(" - In each method we are simply processing rules by reading and modifying the FPSWeaponViewModel's instance data .");
        _.ShowGist("7bba5439faf0b46efa61", "FPSWeaponController.cs");
    }
コード例 #8
0
 protected override void Ending(IDocumentationBuilder _, InteractiveTutorial tutorial)
 {
     _.ImageByUrl("http://i.imgur.com/iprda4t.png");
     _.Paragraph("Now run the game from SceneA, select the gameobject and hit the LoadB button and UnLoadB button from the GameView's inspector.");
     _.LinkToPage <UsingSceneLoaders>();
 }
コード例 #9
0
    public override void GetContent(IDocumentationBuilder _)
    {
        base.GetContent(_);


        _.Paragraph("So if you've made games in Unity before, you may have noticed how easy " +
                    "it is to end up with a mess of components with heavy dependencies.  Unit " +
                    "testing is impossible.  Adding/removing properties or changing the game " +
                    "logic of one component may break components on one, two, or half a dozen " +
                    "other Gameobjects and/or UI elements.  It can easily become a nightmare.");
        _.Break();
        _.Paragraph("In uFrame, an emphasis is placed on separating out the pieces of your game " +
                    "into certain categories (often referred to as \"layers\"), based on this hybrid" +
                    " MVCVM pattern.  The reasoning behind this is to help enforce separation of concerns, " +
                    "and allow you to quickly split things into these categories and think about them " +
                    "up-front.  These parts are defined as:");
        _.ImageByUrl("http://i.imgur.com/oVunJef.png");
        _.Paragraph(" - ViewModels: The objects, including properties and available commands");
        _.Paragraph(" - Controllers: The rules, where you implement logic of commands");
        _.Paragraph(" - Views: The visual/auditory representation of your objects in a game engine environment");
        _.Break();
        _.Paragraph("It gets a little more complicated with the actual implementation, but the chart above " +
                    "is the core concept.  Ideas are always theoretical.  The idea of your game and everything" +
                    " that defines it should technically be able to exist in any environment, whether it's a " +
                    "game engine, a console app, or a physical board game.  A player takes damage and health " +
                    "is decremented; this concept can be represented any number of ways, as a UI health gauge, " +
                    "a damage printout message in a console, or loss of health tokens from a board game player.");
        _.Break();
        _.Break();
        _.Paragraph(
            "In the previous example the Player would be a ViewModel, an object in your game, with a " +
            "Health property.  There would most likely be a TakeDamage command defined in the " +
            "PlayerController, which would handle the rule of decrementing the playerViewModel's Health." +
            "  When the value changes on the Health property, you may have it trigger a view binding on " +
            "the PlayerHUDView which updates a health gauge according to this new value.  The fun part is " +
            "that all it takes to trigger this chain of events is something like:");

        _.CodeSnippet("ExecuteCommand(playerVM.TakeDamage, 10); // player takes 10 damage");
        _.Paragraph("This command can be executed from any controller, or any view that has access to that " +
                    "particular PlayerViewModel instance, usually through some kind of interaction, such as a " +
                    "collision with spikes or an enemy's weapon.  Furthermore, it is important to make a " +
                    "distinction of game logic (which goes on the Controller layer of the design) and " +
                    "visual/auditory/engine-specific logic (which belongs on the View layer).");
        _.Break();
        _.Paragraph("Instead of an EnemyView detecting that it has hit the PlayerView, taking its PlayerViewModel " +
                    "instance, and executing the TakeDamage command on it directly from that EnemyView, it's " +
                    "important to make the distinction that this is game logic and belongs in the Controller " +
                    "layer.  The correct approach that most follows the MVCVM pattern would be to implement " +
                    "some kind of AttackPlayer command on the Enemy element, and pass the playerViewModel of " +
                    "the PlayerView that the EnemyView has hit.");
        _.ShowGist("2db6ead6cc89deb81a5e", "EnemyView, Hit was detected");
        _.Paragraph("Now that you're handling the game logic properly on the Controller layer, the actual logic " +
                    "is no longer dependent on that specific view, and is available to anything that tells the" +
                    " EnemyViewModel to AttackPlayer.");

        _.ShowGist("f79b3de4126c75d5bb03", "Enemy and Player Controllers Command Logic");
        _.Break();
        _.Paragraph("As you can see, there's a method to the madness.  Separating the core logic and state " +
                    "from the \"Monobehaviour\" side of things allows any number of Views to use this data. " +
                    " Under the hood, uFrame manages the state and helps centralize logic.  Everything else " +
                    "is just an expression of that state, a Player getting attacked or taking damage and " +
                    "losing health.");
    }
コード例 #10
0
 protected override void Ending(IDocumentationBuilder _, InteractiveTutorial tutorial)
 {
     _.ImageByUrl("http://i.imgur.com/iprda4t.png");
     _.Paragraph("Now run the game from SceneA, select the gameobject and hit the LoadB button and UnLoadB button from the GameView's inspector.");
     _.LinkToPage<UsingSceneLoaders>();
 }
コード例 #11
0
    protected override void Ending(IDocumentationBuilder _, InteractiveTutorial tutorial)
    {
        _.Paragraph("Now run the game, select the PlayerView gameobject, and type 'Hello World' into the Name field, then press the reset button.  You should also see the console log each change to the property 'Name'");
        _.ImageByUrl("http://i.imgur.com/zrg6r7q.png");

        _.AlsoSeePages(typeof(LoadingAndUnloadingScenes), typeof(CreatingServices));
    }
コード例 #12
0
 private void ExplainKernel(IDocumentationBuilder _)
 {
     _.ImageByUrl("http://i.imgur.com/349glV8.png");
     _.ToggleContentByPage <TheKernel>("The Kernel");
 }