Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by husbandofemily · Jan 28, 2013 at 04:46 PM · javascriptif

Does unity process "false" if statements?

Hi all, please bear with me on this, I tried searching for the answer, but struggling to phrase the question right. Here goes.....

I'm making a zombie game, and writing the AI for the zombies. There're a lot of them, and the AI script is quite long, so I want to cut down the processing spent on them when they're far from the player.

Do I have to make a separate script that measures distance between zombie and player, that turns the AI script on and off? I can do that, but that's an extra script per NPC, per frame, measuring distance.

However, I already do the measuring at the beginning of the existing AI script. My question is - if I put all the rest of the script in an "if" statement tied to distance, will all those lines of code be read and processed if the distance is too great (the statement is false)? If not, it's be cheaper to stick with the one script, with only a few lines being read. If the whole script is read and processed anyway, I'd be better off with two scripts, one turning the other on and off. Anyone able to help please? Sorry for the long winded explanation ;-) Regards Ian

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
3
Best Answer

Answer by Berenger · Jan 28, 2013 at 05:16 PM

Nothing is executed in the scope of a "if(false)". So that would solve your problem.

However, I'd like to make a suggestion. First, you should do an AI loop on a certain frequency, not each frame. So, coroutines. The closer the player is, the lower the frequency must be, obviously.

But instead of computing the distance, which can become quite heavy (even without the sqrt), you could put several game objects under your player, each one with a sphere collider. The first with a radius of five, that's very close from the player, then 20, then 50 etc. That way, your AI can adjust its frequency depending of which collider it enters, or leave. You could modify the complexity of the AI as well.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image whydoidoit · Jan 28, 2013 at 07:34 PM 1
Share

You mean the closer they are the higher the frequency right? :)

avatar image
2

Answer by Bunny83 · Jan 28, 2013 at 05:16 PM

No, Unity or Mono / .NET doesn't execute the content of an if statement that is false. That's the point of an if statement ;)

If you worry about performance you might want to put your code in a CoUpdate function. A coroutine which just runs slower than Update.

 function Start()
 {
     CoUpdate();
 }
 
 function CoUpdate()
 {
     while(true)
     {
         // Your code here
         yield new WaitForSeconds(0.1);
     }
 }

This will make your code only being executed 10 times per sec.

You can also use InvokeRepeating(Fattie would suggest this first), but i don't like it ;)

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Eric5h5 · Jan 28, 2013 at 07:27 PM 0
Share

I'd suggest InvokeRepeating too...not fond of the string, but it's more lightweight than a coroutine.

avatar image
1

Answer by whydoidoit · Jan 28, 2013 at 08:09 PM

One more thought, based on the fact you need to do distance checks to work stuff out, a good way around that is to use a simplified 2D representation of the world to see if something is close to the player. For instance you could check if the enemy was within 40 and 80 world units of the player (in x and z) by dividing the world into 40 world unit squares and seeing if the player is in the current cell or any adjacent one. This doesn't require square roots and only requires that each item writes and removes itself from the grid as it moves. This is also a good technique for lots of things that involve proximity and the like. For instance I use it to keep 100s of characters apart without raycasts or built in collision detection.

I've built a simple(ish) class to support it.

SupportClasses.cs

 public class DefaultDictionary< TK,TR > : Dictionary< TK,TR>
 {
     public new virtual TR this[TK index]
     {
         get
         {
             if (ContainsKey(index))
             {
                 return base[index];
             }
             return default(TR);
 
         }
         set
         {
             base[index] = value;
         }
     }
 
     public T Get< T >(TK index) where T : TR
     {
         return (T)this[index];
     }
 
 
 
 }
 
 
 public class Index< TK,TR > : DefaultDictionary< TK,TR > where TR : class, new()
 {
 
     public event Action< TK, TR, TR> Setting = delegate { };
     public event Action< TK, TR> Getting = delegate { };
 
     public override TR this[TK index]
     {
         get
         {
             if (ContainsKey(index))
             {
                 return base[index];
             }
             var ret = new TR();
             if (ret is INeedParent)
             {
                 (ret as INeedParent).SetParent(this, index);
             }
             base[index] = ret;
             Getting(index, ret);
             return ret;
         }
         set
         {
             if (Setting != null)
             {
                 TR current = null;
                 if (base.ContainsKey(index))
                 {
                     current = base[index];
                 }
                 Setting(index, current, value);
             }
             base[index] = value;
         }
     }
 }


CollisionGrid.cs

 using UnityEngine;
 using System.Linq;
 using System.Collections.Generic;
 using System;
 
 public class GridCellPosition
 {
     public int z;
     public int x;
     
     static readonly Index< int, Index< int, GridCellPosition>> cache = new Index< int, Index< int, GridCellPosition>>();
     
     public static GridCellPosition Get(int x, int z)
     {
         GridCellPosition cell;
         if(!cache[x].TryGetValue(z, out cell))
         {
             cell = new GridCellPosition
                 {
                     x = x,
                     z = z
                 };
             cache[x][z] = cell;
             
         }
         return cell;
     }
     
     public static implicit operator GridCellPosition(Vector3 position)
     {
         return Get(Mathf.FloorToInt(position.x),
             Mathf.FloorToInt(position.z));
     }
 
 
     public GridCellPosition Offset(int offsetX, int offsetZ)
     {
         return Get(x + offsetX, z + offsetZ );
     }
     
     public static GridCellPosition operator / (GridCellPosition pos, int value)
     {
         return Get(pos.x / value, pos.z / value );
     }
     
     public static GridCellPosition operator * (GridCellPosition pos, int value)
     {
         return Get(pos.x * value,  pos.z * value );
     }
     
 }
 
 
 public class CollisionGrid< T>
 {
     public int size = 5;
     public virtual bool Add(GridCellPosition position, T item) {return false; }
     public virtual IEnumerable< T> Get(GridCellPosition position) { return null; }
     public virtual IEnumerable< T> Get(GridCellPosition position, float width, float height) {return null;}
     
     public IEnumerable< T> this[GridCellPosition position]
     {
         get
         {
             return Get(position);
         }
     }

     public virtual bool CheckCell(GridCellPosition position) { return false; }

     readonly List< T> _emptyList = new  List<T>();
     
     public IEnumerable< T> this[Component position]
     {
         get
         {
             return position == null ? _emptyList : Get(position.transform.position);
         }
     }
     
     public virtual bool Add(T item)
     {
         if (item == null)
             throw new Exception("Trying to add null to a grid");
         if (item is Transform)
         {
             return Add((item as Transform).position, item);
         }
         if(item is Component)
         {
             return Add((item as Component).transform.position, item);
         }
         if(item is GameObject)
         {
             return Add((item as GameObject).transform.position, item);
         }
         throw(new Exception("Cannot get a position from " + item.GetType().FullName));
     }
     public virtual void Clear() {}
     public virtual void Remove(T item) {}
     public virtual void Remove(GridCellPosition position, T item) {}
     
 }
 
 public class SparseCollisionGrid< T>  : CollisionGrid< T> {
     readonly Index< GridCellPosition, HashSet<T>> _grid = new Index< GridCellPosition, HashSet< T>>();
     
     public override bool Add(GridCellPosition position, T item)
     {
         position /= size;
         var result = InternalCheck(position, item);
         _grid[position].Add(item);
         return result;
     }
     
     public override void Remove(GridCellPosition position, T item)
     {
         position /= size;
         _grid[position].Remove(item);
     }
     
     public override void Remove(T item)
     {
         if (item is Transform)
         {
             Remove((item as Transform).position, item);
         }
         if(item is Component)
         {
             Remove((item as Component).transform.position, item);
         }
         else if(item is GameObject)
         {
             Remove((item as GameObject).transform.position, item);
         }
         else throw(new Exception("Cannot get a position from " + item.GetType().FullName));
     }
     
     public override IEnumerable< T> Get(GridCellPosition position)
     {
         position /= size;
         //var list = Factory.New< List< T>>();
         var list = new List< T>();
         list.AddRange(_grid[position.Offset(0,0)]);
         list.AddRange(_grid[position.Offset(0,1)]);
         list.AddRange(_grid[position.Offset(1,0)]);
         list.AddRange(_grid[position.Offset(1,1)]);
         list.AddRange(_grid[position.Offset(-1,0)]);
         list.AddRange(_grid[position.Offset(0,-1)]);
         list.AddRange(_grid[position.Offset(1,-1)]);
         list.AddRange(_grid[position.Offset(-1,1)]);
         list.AddRange(_grid[position.Offset(-1,-1)]);
         return list;
     }
     
     public override IEnumerable< T> Get (GridCellPosition position, float width, float height)
     {
         width = Mathf.FloorToInt(width/size)+1;
         height = Mathf.FloorToInt(height/size)+1;
         position /= size;
         //var list = Factory.New< List< T>>();
         var list = new List< T>();
         for(var x = 0; x < width + 2; x++)
         {
             for(var z = 0; z < height+2; z++)
             {
                 var result = _grid[position.Offset(x, -z)];
                 if(result!=null)
                     list.AddRange(result);
             }
         }
         return list;
     }
     
     
     
     public override bool CheckCell(GridCellPosition position)
     {
         return _grid[position].Count > 0;
     } 
     
     
     
     public override void Clear()
     {
         _grid.Clear();
     }
     
 }

Using it

You use it by defining a collision grid and giving it a size

  public static CollisionGrid< AnyScriptOrComponent> collisionGrid = new SparseCollisionGrid< AnyScriptOrComponent>();
  ...
  collisionGrid.size = 40;

Then thing that wants to be detected adds and removes itself as it moves (removing first really)

  void Update()
  {
       collisionGrid.Remove(this);
       ...
       transform.position += Vector3.right * 2;
       ...
       collisionGrid.Add(this);
  }

Then to get all of the items within adjacent cells (or the current cell)

   foreach(var item in collisionGrid[this])
   {
       if(item == this) continue;
       //Do something with the neighbour
   }

If you were just looking for the player then you could not add the enemies at all and just have the player in there, then its a simple check

   if(collision.CheckCell(transform.position))
   {
       //Player is close
   }
   else
   {
       //Not so much
   }

 
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Eric5h5 · Jan 28, 2013 at 08:23 PM 0
Share

The issue seems to be related to HT$$anonymous$$L tags, so as a work-around always uses spaces, such as foo< bar >.

avatar image whydoidoit · Jan 28, 2013 at 08:27 PM 0
Share

Thanks Eric, I was pulling my hair out - some were working (guess it knew they weren't tags) but it really didn't like < TR!!

avatar image whydoidoit · Jan 28, 2013 at 08:33 PM 0
Share

Note this technique is very powerful when you need to test many things against many other things - it is certainly possible a distance check against a single point would be faster in circumstances that only require that. All depends really.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

14 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

car moving sideways 1 Answer

Else and If 2 Answers

If statement checking material tint color 0 Answers

I'm new to coding. BCE0044 error. How do I fix? When I delete the extra } it gives me 23 errors 3 Answers

"If player is moving, return true" - not entirely working 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges