Forum Replies Created

Viewing 15 posts - 151 through 165 (of 1,177 total)
  • Author
    Posts
  • in reply to: Possible to change a waypointpatrol looptype at runtime? #34560

    prime
    Keymaster

    The waypoint route field in a bt node is an Expression. That means you can use a variable there rather than assigning it at design time. Just use a variable in your BT, then assign that variable to characters as appropriate.

    in reply to: Why can't I edit my BT #34558

    prime
    Keymaster

    The Reload button is on the right hand side with the Import/Export XML buttons.

    The Move action is not a decision/container node, so you can’t add actions to it (indented under it). What you can do is place the action you want to perform after reaching your move target in line right after your Move. That’s what Sequencer nodes are good for. So your structure will probably look something like this:

    PARALLEL (SUCCEED ON ANY)
    -DETECT (REPEAT FOREVER)
    -SEQUENCER
    —-MOVE
    —-ACTION

    • This reply was modified 1 month, 1 week ago by  prime.
    in reply to: Detect multiples #34551

    prime
    Keymaster

    There are a couple of options for you here:

    1) You could write a Sensor Filter. The sensor filter operates on the full list of detected aspects, so it may be the right place to pick the best one.

    2) Write a custom detect node. Grab your sensor using ai.Senses.GetSensor. Call sensor.MatchAspectName. Then look at the sensor.Matches property to get the full list of results.

    RAINSensor tSensor = ai.Senses.GetSensor("Visual Sensor");
    tSensor.MatchAspectName("someaspect");
    foreach (RAINAspect tAspect in tSensor.Matches)
    {
    //do whatever
    }
    • This reply was modified 1 month, 1 week ago by  prime.
    in reply to: Why can't I edit my BT #34550

    prime
    Keymaster

    Are you using Behavior Tree bindings? BT bindings will appear in the tree as regular nodes after the AI is run and they are bound. However they won’t be editable.

    Try hitting the reload button in the BT Editor.

    in reply to: How to stop at last waypoint #34549

    prime
    Keymaster

    I can’t reproduce that problem. Can you share an example scene? This is with 2.1.6? Seems like an issue like that existed in an old version…

    Also, your parallel is set to Succeed on what? Any or All? And your Run animation, is it set to Looping in the RAIN Animator?

    in reply to: Picking RAIN's Brain #34546

    prime
    Keymaster

    Here’s a sensor that is totally custom:

    using System.Collections.Generic;
    using RAIN.Core;
    using RAIN.Perception;
    using RAIN.Perception.Sensors;
    using RAIN.Entities.Aspects;
    using RAIN.Serialization;
    using UnityEngine;
        /// <summary>
        /// Goal Sensor is used to detect goals that game designers have placed in the scene.  These indicate objetives for the AI
        /// </summary>
        [RAINSerializableClass, RAINElement("Goal Sensor")]
        public class GoalSensor : RAINSensor
        {
            /// <summary>
            /// Maximum distance an Aspect can be from the Sensor
            /// </summary>
            [RAINSerializableField(Visibility = FieldVisibility.ShowAdvanced, ToolTip = "Sensor clipping distance")]
            private float _range = 10f;
            [RAINSerializableField(Visibility = FieldVisibility.ShowAdvanced, ToolTip = "Whether to include the AI Body when matching Aspects")]
            private bool _canDetectSelf = false;
            /// <summary>
            /// A list of matches that is maintained after a MatchAspect call.  This is used instead of returning matches directly in
            /// order to improve performance and limit array copies
            /// </summary>
            private List<RAINAspect> _matches = new List<RAINAspect>();
            /// <summary>
            /// Maximum distance an Aspect can be from the Sensor
            /// </summary>
            public virtual float Range
            {
                get { return _range; }
                set { _range = value; }
            }
            /// <summary>
            /// Toggle whether MatchAspect will match Aspects that are part of the AI Body hierarchy
            /// </summary>
            public virtual bool CanDetectSelf
            {
                get { return _canDetectSelf; }
                set { _canDetectSelf = value; }
            }
            /// <summary>
            /// Get a list of the aspects that were found during the last MatchAspect or MatchAspectName call on this sensor.
            /// </summary>
            public override IList<RAINAspect> Matches
            {
                get { return _matches.AsReadOnly(); }
            }
            /// <summary>
            /// Test to see if the Sensor can detect a particular RAINAspect.  This requires an exact object match (i.e., an object
            /// comparison will be done against all potential matches.)  The Match list will contain the RAINAspect if it is detected.
            /// </summary>
            /// <param name="aAspect">The RAINAspect to match</param>
            public override void MatchAspect(RAINAspect aAspect)
            {
                _matches.Clear();
                if ((aAspect == null) || (!aAspect.IsActive) || (aAspect.Entity == null) || (aAspect.Entity.Form == null) || (!aAspect.Entity.Form.activeInHierarchy))
                    return;
                IList<RAINAspect> potentialMatches = SensorManager.Instance.GetAspects(GoalAspect.cnstAspectType);
                float tSqrRange = Range * Range;
                if (potentialMatches.Contains(aAspect))
                {
                    if (TestVisibility(aAspect, tSqrRange))
                        _matches.Add(aAspect);
                }
                Filter(_matches);
            }
            /// <summary>
            /// Fill the Match list with all aspects that match the given aspect name.  Match by name is the normal
            /// usage of Aspects.
            /// </summary>
            /// <param name="aAspectName">The name to match.</param>
            public override void MatchAspectName(string aAspectName)
            {
                _matches.Clear();
                IList<RAINAspect> potentialMatches = SensorManager.Instance.GetAspects(GoalAspect.cnstAspectType);
                float tSqrRange = Range * Range;
                foreach (RAINAspect potentialAspect in potentialMatches)
                {
                    if ((potentialAspect == null) || (!potentialAspect.IsActive) || (potentialAspect.Entity == null) || (potentialAspect.Entity.Form == null) || (!potentialAspect.Entity.Form.activeInHierarchy))
                        continue;
                    if ((potentialAspect.AspectName == aAspectName) && (TestVisibility(potentialAspect, tSqrRange)))
                        _matches.Add(potentialAspect);
                }
                Filter(_matches);
            }
            /// <summary>
            /// Fill the match list with all aspects detected by this sensor.
            /// </summary>
            public override void MatchAll()
            {
                _matches.Clear();
                IList<RAINAspect> potentialMatches = SensorManager.Instance.GetAspects(GoalAspect.cnstAspectType);
                float tSqrRange = Range * Range;
                foreach (RAINAspect potentialAspect in potentialMatches)
                {
                    if ((potentialAspect == null) || (!potentialAspect.IsActive) || (potentialAspect.Entity == null) || (potentialAspect.Entity.Form == null) || (!potentialAspect.Entity.Form.activeInHierarchy))
                        continue;
                    if (TestVisibility(potentialAspect, tSqrRange))
                        _matches.Add(potentialAspect);
                }
                Filter(_matches);
            }
            /// <summary>
            /// Perform a visibility test on an aspect.  the square of the range is passed in to give a slight
            /// speed improvement on distance checks
            /// </summary>
            /// <param name="aAspect">The aspect to check</param>
            /// <param name="aSqrRange">The square of the Range</param>
            /// <returns>true if the aspect is within sensor range and angles and passes visibility tests, false otherwise</returns>
            protected virtual bool TestVisibility(RAINAspect aAspect, float aSqrRange)
            {
                if (aAspect.Entity.Form == null)
                    return false;
                Transform mountTransform = aAspect.Entity.Form.transform;
                if (aAspect.MountPoint != null)
                    mountTransform = aAspect.MountPoint.transform;
                if ((!CanDetectSelf) && (mountTransform != null) && ((mountTransform == AI.Body.transform) || (mountTransform.IsChildOf(AI.Body.transform))))
                    return false;
                if ((aAspect.Position - Position).sqrMagnitude > aSqrRange)
                    return false;
                return true;
            }
        }

    along with a matching custom aspect

    using UnityEngine;
    using System.Collections;
    using RAIN.Serialization;
    using RAIN.Entities;
    using RAIN.Entities.Aspects;
        [RAINSerializableClass]
        public class GoalAspect : RAINAspect
        {
            [RAINSerializableField(Visibility = FieldVisibility.Show, ToolTip = "Goal")]
            private string goal;
            public const string cnstAspectType = "Goal";
            public string Goal
            {
                get { return goal; }
                set { goal = value; }
            }
            public override string AspectType
            {
                get { return cnstAspectType; }
            }
        }
    • This reply was modified 1 month, 1 week ago by  prime.
    • This reply was modified 1 month, 1 week ago by  prime.
    in reply to: Picking RAIN's Brain #34545

    prime
    Keymaster

    How to create a new sensor (simply) based on the visual sensor:

    using UnityEngine;
    using System.Collections.Generic;
    using RAIN.Core;
    using RAIN.Serialization;
    using RAIN.Perception;
    using RAIN.Perception.Sensors;
    using RAIN.Entities;
    using RAIN.Entities.Aspects;
    [RAINSerializableClass, RAINElement("Custom Visual Sensor")]
    public class CustomVisualSensor : VisualSensor
    {
        protected override bool TestVisibility(RAINAspect aAspect, float aSqrRange, Matrix4x4 aSensorSpace)
        {
            //TestVisibility is the method that determines whether an aspect is within sensor range
            //Override the method to do your own test, or accept the result and do some post processing
            return base.TestVisibility(aAspect, aSqrRange, aSensorSpace);
        }
    }
    in reply to: UFPS integration #34537

    prime
    Keymaster

    I know a couple of Adv Warfighter users have worked on integrating the two. We could potentially provide direct support for that. What would you be looking for in an integration? Just integrating the damage systems? The bullet/projectile effects? Swapping the Adv Warfighter First Person Controller with the one from UFPS?

    in reply to: Picking RAIN's Brain #34536

    prime
    Keymaster

    Would you prefer to base your sensor on the existing Visual Sensor, or write one completely from scratch?

    in reply to: Chasing player on navmesh #34534

    prime
    Keymaster

    Something else must be going on. For RAIN, there’s no difference between the two methods. Do you have a project you can share that demonstrates the problem? Also, are you using the very latest RAIN? (2.1.6)

    in reply to: Global variables in and out tree Behavior #34533

    prime
    Keymaster

    I don’t think I understand your question. Maybe this will help:

    All variables that are used in a RAIN Behavior Tree come from the AI.Memory of the AI that is running the tree. So if 3 different AI are running the same behavior tree, they will each have their own variables with their own values.

    If you want to send information to an AI to use in its behavior tree, you must do so by creating or modifying a variable in that AI’s memory. You can do so on any AI by calling AI.WorkingMemory.SetItem() from code. Usually in code you will have access to the AIRig component rather than the AI itself, so you would call rig.AI.WorkingMemory.SetItem()

    So, to “warn the others” you would grab each other AI’s rig and do the SetItem call on each.

    in reply to: Same BT with different variables #34527

    prime
    Keymaster

    Glad things are working.

    I’ll just mention this for anyone else who may be reading - switching to Unity Pro should have no impact on the functionality of RAIN. I’m guessing that the upgrade just caused something else to get reset or reserialized, which resolved the issue.

    in reply to: Chasing player on navmesh #34526

    prime
    Keymaster

    Sure. Do just what you said - use the player’s transform/game object directly. Variables that contain transforms/game objects are valid move targets for move nodes.

    For example, when you use a sensor and enter a variable name in the Form Variable field, it’s the game object that gets bound.

    in reply to: [RAIN Starter Kit] Basic Behaviors #34523

    prime
    Keymaster

    If there’s a behavior that you’d like to see demonstrated in the Starter Kit, just ask. We’re looking for suggestions and will be making frequent updates to the project based on your requests.

    Coming next:
    One way waypoint route following
    How to use waypoint paths
    How to path across 2 Navigation meshes
    Movement using a Mecanim animated character

    in reply to: How to stop at last waypoint #34522

    prime
    Keymaster

    Setting the loop mode to One Way will make the AI stop at the last waypoint.

    I just created a quick scene with a waypoint route, created a behavior tree with a waypoint patrol node set to one way (and a Move node as a child) and ran it. Does just what you want. If the AI is not stopping then something else is going on in the behavior tree to cause it to keep moving. How is your BT set up?

Viewing 15 posts - 151 through 165 (of 1,177 total)