Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Sunday, May 19, 2013

OpenInFileBrowser Code

I realized there's a debacle right now in the Unity Wiki Website over its content being under the Creative Commons License.

So to make sure there's no legal problems with using this code, here's a re-upload of my OpenFileInBrowser code for Unity here in my blog.

As always, I put this code in Public Domain as it's quite simple but good enough to be shared.


public static class OpenInFileBrowser
{
   public static bool IsInMacOS
   {
      get
      {
         return SystemInfo.operatingSystem.IndexOf("Mac OS") != -1;
      }
   }
 
   public static bool IsInWinOS
   {
      get
      {
         return SystemInfo.operatingSystem.IndexOf("Windows") != -1;
      }
   }
 
   [MenuItem("Window/Test OpenInFileBrowser")]
   public static void Test()
   {
      //string path = "/Users/Ferds/Unity Projects/BuildReportTool/BuildReportUnityProject/Assets/BuildReportDebug";
      //string path = "/Users/Ferds/Unity Projects/BuildReportTool/BuildReportUnityProject/Assets/BuildReportDebug/EditorMorel.log.txt";
      //string path = "/Users/Ferds/UnityBuildReports/";
      string path = "/Users/Ferds/UnityBuildReports/test4.xml";
 
      Open(path);
   }
 
 
   public static void OpenInMac(string path)
   {
      bool openInsidesOfFolder = false;
 
      // try mac
      string macPath = path.Replace("\\", "/"); // mac finder doesn't like backward slashes
 
      if (Directory.Exists(macPath)) // if path requested is a folder, automatically open insides of that folder
      {
         openInsidesOfFolder = true;
      }
 
      //Debug.Log("macPath: " + macPath);
      //Debug.Log("openInsidesOfFolder: " + openInsidesOfFolder);
 
      if (!macPath.StartsWith("\""))
      {
         macPath = "\"" + macPath;
      }
      if (!macPath.EndsWith("\""))
      {
         macPath = macPath + "\"";
      }
      string arguments = (openInsidesOfFolder ? "" : "-R ") + macPath;
      //Debug.Log("arguments: " + arguments);
      try
      {
         System.Diagnostics.Process.Start("open", arguments);
      }
      catch(System.ComponentModel.Win32Exception e)
      {
         // tried to open mac finder in windows
         // just silently skip error
         // we currently have no platform define for the current OS we are in, so we resort to this
         e.HelpLink = ""; // do anything with this variable to silence warning about not using it
      }
   }
 
   public static void OpenInWin(string path)
   {
      bool openInsidesOfFolder = false;
 
      // try windows
      string winPath = path.Replace("/", "\\"); // windows explorer doesn't like forward slashes
 
      if (Directory.Exists(winPath)) // if path requested is a folder, automatically open insides of that folder
      {
         openInsidesOfFolder = true;
      }
      try
      {
         System.Diagnostics.Process.Start("explorer.exe", (openInsidesOfFolder ? "/root," : "/select,") + winPath);
      }
      catch(System.ComponentModel.Win32Exception e)
      {
         // tried to open win explorer in mac
         // just silently skip error
         // we currently have no platform define for the current OS we are in, so we resort to this
         e.HelpLink = ""; // do anything with this variable to silence warning about not using it
      }
   }
 
   public static void Open(string path)
   {
      if (IsInWinOS)
      {
         OpenInWinFileBrowser(path);
      }
      else if (IsInMacOS)
      {
         OpenInMacFileBrowser(path);
      }
      else // couldn't determine OS
      {
         OpenInWinFileBrowser(path);
         OpenInMacFileBrowser(path);
      }
   }
}

Wednesday, May 8, 2013

My first time selling on the Unity Asset Store

It started with this. Someone was having trouble with his build size so I explained that thing about the Editor.log, in that it actually had info on the breakdown of your build's file size!

So I went and whipped up a simple front-end for the log's build info over a weekend.


Then I asked the forums if they'd be interested in having it on the Asset Store. A handful of people agreed. Then I thought, why don't I try selling it, maybe for just a few bucks to see what's the experience of selling on the Asset Store? We need the money anyway.

There was a discussion in a LinkedIn Unity group where someone was adamant that I should give it for free and that I'd only get a few bucks out of it. It was quite a bummer. It was a bit depressing actually.

So I set it to $2 as an introductory price and waited how it would turn out. The plan went that I'd keep it as $2 for one week then set it to the standard price.

David Helgason even retweeted my tweet about it. I guess it was like... I don't know. Stevie Wonder humming a tune you just made up? It was unexpectedly cool.

David's a pretty awesome guy.

I placed a public poll on my forum thread asking "How much would you be willing to pay for this plugin?" The choices I put where $2, $5, and $10. Majority answered $5. I guess they're not that cheap that they'd settle for the lowest price. Seems like $10 is too much too. So we figured $5 was the sweet spot.

By the end of the week I then set it to $5, only to realize that price changes do, in fact, still have to go through review by the Asset Store team. Then David again helped me out. It's quite awesome that a big company like Unity still has the time to help out the little guys using their products.

So the $2 sale went for approximately 9 days. A total of 117 people bought it during that period.

I'd shudder to think that $163 is only a few bucks. Must be there's a really high standard of living where that guy is.

Now that the selling price is $5, the amount of people who purchased is about 1/3rds lesser. I still got higher sales overall though.

It's selling quite well, for something I just whipped up over the weekend (though I do improve it every now and then). It's managed to get consistent five stars from reviews. It even got to the Asset Store front page one time.


Here's the link to the Asset Store page: http://u3d.as/4u2

Here are some things I'd like to share for my experience:

  1. If a customer previously purchased directly from you (not from Asset Store), it cannot be unlocked for them in the Asset Store for free. They have to buy it again in the Asset Store.
  2. Your publisher page is quite bare-bones. There's no sales graph or overall total sales. There's only the sales per month, and you can only view one month at a time. Switching from one month to the next is quite slow (for my Internet connection).
  3. Related to that, when a customer posts a user review, you get no email notification about it, or any notification whatsoever. You have to visit your asset store product's page every now and then to see if someone has a complaint in their review, or some misunderstanding you'd like to clear up. UT's take on this is that it's your job to facilitate communication with your customers, but something like an option for email notification in this case would be nice, no?
  4. The ways you could offer support is usually via Twitter, email, tell them that they can PM you in the Unity forums, or if you have a forum thread about your product, give them a link. You'd usually put such links in your Asset Store product page's description.
  5. I'd like to reiterate the standard warning: If enough customers complain that they are not getting adequate support from you, UT has the right to take down your product.
  6. If your product is something visual, then potential customers will like to see video demos, or web interactive demos to see an example of how your product is useful. Their mindset is: "So what's this Asset Store package? Will it be useful in the project I'm working on?" That second question is what you need to address. And you do it by showing potential scenarios of how it's used, i.e. demos.
  7. If your product is purely code instead, perhaps a video tutorial how to use it can also work. At the very least, post some screenshots. Surely there's something visually presentable that you can show?
  8. If your asset store package has code, customers will appreciate it if you separate your code into your own namespace as much as possible to avoid name conflicts.
  9. Use the lowest possible version of Unity when releasing your asset package. Since they are distributed as .unitypackage files, the version of Unity used to create the .unitypackage is also the lowest version allowed to import that file. Frankly, I think this is just a conspiracy to force you to upgrade your licenses. I keep an installation of Unity 3.5.3 in this case.
  10. Selling on the Unity Asset Store is a non-exclusive deal. I.e. you are free to sell your product via other stores (ex. gameprefabs.com)
  11. You can't verify if a person who emailed you really purchased your product just using your publisher dashboard alone. You can, however, email the Asset Store Team to verify for you if someone indeed purchased it. Dantus in the Unity forums points out email isn't necessary. All you need to do to verify if someone purchased your asset is to ask them for their Invoice Number. Then in your publisher dashboard, there's a tab called "Verify Invoice". You can type the Invoice Number there to verify someone's purchase. (For example, say, someone reported a bug. So you fix it and would like to send it to the bug reporter to test the fix on his machine. What if he didn't really purchase your product? You better verify to be safe.)
  12. Possible places you can use to advertise your asset package:
    1. Main Unity Forums
    2. Google+ Unity Community
    3. LinkedIn Unity Group
    4. Unity South East Asian Mailing List (only if you're based in South East Asia!)
    5. Unity3d Subreddit


Friday, February 3, 2012

Tactics Ensemble: Movement

This is an experiment on the movement mechanic of the combat for Victis.


The violet area is the limits of where the tiny white guy in the middle can move to.

While the game is turn-based, the map does not make use of grids. Basically I just used my idea from Death Zone Zero, which in turn, got its idea from RTS games in general. If you've played tabletop wargames, things work that way.

Movement is calculated as a stamina cost per meter, not a predefined value. He has, in this example, 100 stamina points, and movement is 2 stamina points per meter.

Other actions like attacking also consumes stamina, so the player has to be mindful of deciding when to conserve stamina for movement or actions. Basically the same with Action Points of XCOM games.

Furthermore, climbing upwards has a higher stamina cost of 10 stamina points per meter, which accounts for the irregular shape of the movement range.

The currently selected destination is shown with the X-mark on the ground there, with the distance to that shown at the top left, together with the total stamina cost to move there. You can see the stamina cost is roughly twice the distance. This is correct since again, I've set it to be 2 stamina points per meter. The disparity is from the fact that the terrain is bumpy, and since climbing upwards is more costly, the destination's stamina cost reflects this.

Tuesday, January 31, 2012

Input Recorder For Unity

Being able to record player input is invaluable for bug reports so players can submit their recorded play session and you can easily watch how the bug manifests.

After development, its also useful for the end-user to share his play experience to other people, or to allow other people to study other player's tactics.

So I saw this:


And saw how simple the input display was. So I went to try the same thing in Unity:


This only records input so far. Feeding those recorded input back to the game is another matter. Its also not possible to feed those data back into Unity's input system as far as I know. So I can't make Input.GetAxis() return the recorded input data.

Instead I would have to make my own system, like, say, RecordedInput.GetAxis(), RecordedInput.GetButton(), and so on. Feeding that data to the GUI system is also another matter.

Monday, December 19, 2011

Collaborative Diffusion/Influence Maps For Obstacle Avoidance

There was in the Unity forums, a post asking about how to implement flanking behaviour obstacle avoidance. I took interest because I've been wondering how to do that also.

Another user posted a link to a page explaining Collaborative Diffusion. From what I understand, its like influence maps, but once an agent passes through a node, that node's influence becomes zero, signifying its impassable now that he's there.


So I tried implementing it in Unity here: http://dl.dropbox.com/u/25260770/PathfindingTest/WebPlayer.html (you'll need to install the Unity plugin for your browser).

Left click to set the new attraction point or whatever its supposed to be called.

I'm pretty sure some of my code is a bit naive. Its only in certain situations do the agents will exhibit flanking behaviour. Some agents end up stuck, and I don't like the bee-like zig-zag movement they make.

Also I think it would be better to couple this with typical A*, such that, the path created by the A*, the area of the influence map that that path takes up, will be set to zero influence. Its as if the agent will be saying "to my allies, this is the path I'll take, don't cross it, its mine only. find your own path".

Tuesday, April 5, 2011

Thursday, March 10, 2011

HHHhUUUUuRRRrrrRRrrRRRRR! A RECKLESS DISREGARD FOR POLYCOUNT


"I'd check it out, but I have to install some shitty plugin. 0/10."
- Anon

Your framerate is your life. In HHHhUUUUuRRRrrrRRrrRRRRR, you fight badly created 3d models in a never-ending effort to bring your framerates to an acceptable value.

HHHhUUUUuRRRrrrRRrrRRRRR is a non-work project I'm making in my free-time. Only a work-in-progress main menu intro animation has been uploaded so far. Check it out here: http://anomalousunderdog.herobo.com/Unity/Hurrr/

Monday, March 7, 2011

Back To The Oct 29 2099

Check it out, my first try at uploading something to the Unity Asset Store. Its pending review but here it shows the preview of what it'll look like back... to the future!



UPDATE: Here's the link: http://u3d.as/content/anomalous-underdog/unity-lua-interface-library/1AY

Saturday, February 26, 2011

Random Random Word Generator updated!

Its now called Random Name Generator to make it more specific.

Method 3 is added, making a word that follows some rules based on the last letter chosen.

Recently I got "Narlet", which I think is a very good female name.

http://anomalousunderdog.herobo.com/RandomWord/

Friday, February 25, 2011

Random Random Word Generator

I made a random word generator a very long time ago when I was a kid.

The first one was made in Visual Basic 6, now I made a new one as a web page, also using this opportunity to learn jQuery and jQuery UI.

Its going to spout out nonsensical words that likely don't exist in any language (however, just now I got the word "Sayako" which I think is a Japanese name). I used it to help me make up names for my stories.

Method 1 generates a word out of all English letters without any pattern. Method 2 tries to be more refined by alternating between a consonant and a vowel when choosing letters.

A little story: One time in the first version of this program, I just kept on clicking the Generate button rapidly and it spewed this sequence of words:
(a bunch of random words)
I
AM
(then a bunch of random words)

Did my computer gain sentience, or was God talking to me?

Give it a try: http://anomalousunderdog.herobo.com/RandomWord/

Friday, February 11, 2011

Dependency Hell

Last login: Fri Feb 11 01:20:48 on ttys000
mac:~ user$ sudo port install libusb-devel +universal
--->  Computing dependencies for libusb-devel
--->  Dependencies to be installed: autoconf help2man gettext expat libiconv gperf ncurses ncursesw p5-locale-gettext perl5 perl5.8 m4 automake git-core curl curl-ca-bundle libidn openssl zlib pkgconfig p5-error python27 bzip2 db46 gdbm readline sqlite3 rsync popt libtool

You need all this shit just to get a usb library working? Opeen Soooouuuuuurce!!!!

Its like I'm really in Linux!

Tuesday, February 8, 2011

AssetBooruCh

Somewhere along the way we discussed the need to better organize our 3d models, reference images, concept sketches, fonts, music, and sound effects in the office.

This reminded me of ResourceSpace. I tried it out on a local dev test site.

I have to say, its meant by default for graphic design, web design and those areas. Properties like Country or Camera Model are useless to textures, while you need more information for 3d models, such as polygon count.

I set out planning a different digital asset management tool that would work for us.

Meanwhile, people in the ResourceSpace Google groups explained that thankfully you can add new resource types and change properties of existing ones. Seems like I may use ResourceSpace after all.

However, my plans started diverting from ResourceSpace and I really thought I should look into it more:

  • Upload any kind of file. Plugins are made to handle a specific asset type, like images, 3d models, textures, fonts, etc. 3d models show interactive thumbnails, videos have streaming flash video previews, and fonts can be previewed interactively (edit the text that is displaying the font).
  • Danbooru-style tag-based organization. Assets are tagged and a sophisticated search system can be used to search assets based on its tags and properties.
  • Imageboard based commenting system. Comments can be quoted, replied upon, with images and links properly parsed.
  • Voting system. Assets can be rated from 0 to 5. Using the search system mentioned above, its easy to find popularity trends of certain assets. Comments can be voted up or down. Upvoted comments appear at the top while downvoted comments are hidden by default.
  • AJAX. Most user operations do not require reloading the page. Search result pages are loaded without needing to refresh the page, similar to Google Images. Inputting values for tags give suggestions based on the word currently being typed.
  • History graphs. Show history graphs of changing values like number of times an asset was viewed, average rating of an asset, number of comments to an asset, etc.
  • Bookmark search results or subscribe to them as RSS feeds so you can be notified of any changes.
I shall therefore call it AssetBooruCh, and I'm looking at releasing it as an open source project.

Sunday, January 30, 2011

I am not your mom

Jan 30 17:49:32 <Tayfe> AnomalusUndrdog: mom, maybe i found the problem...
Jan 30 17:49:51 <AnomalusUndrdog> I am not your mom
Jan 30 17:50:03 <VILE> lol
Jan 30 17:51:04 <Tayfe> AnomalusUndrdog: mom - one moment pls^^
Jan 30 17:51:19 <AnomalusUndrdog> I am not even female
Jan 30 17:51:36 <Tayfe> AnomalusUndrdog: maybe it's a problem that i use the same code on the car, too?

Oh IRC chat, you so crazy.

Join in the fun: #unity3d in freenode.

In other news, from the same IRC chat, I just learned about partial classes. A way to split your class definition into separate files, which is what I did back in C++ Torque days as my classes get to be too big. In most situations, this is doing it wrong, because classes getting big is a sign that I'm putting too much functionality in one place and I should separate distinct functionalities into separate classes in the first place.

Monday, June 14, 2010

Death Zone Zero: Minor Update: Client Server Network

The Battle Server is slowly starting to take shape. Players can log-in, get their unit data from the database, and load units on the battlefield. Can't control them yet though. But with the work I've done in the single player demo, the template is there. I just need to add the multiplayer network part to it.

Photobucket

One thing I don't like about Unity is the lack of better serialized data transmissions across the network. I made a formal request about it here: http://feedback.unity3d.com/forums/15792-unity/suggestions/824649-better-network-serialize-commands
Oftentimes I need to send a bulk of data to the client to initialize his data. I have 2 options for doing this: RPC (Remote Procedural Call) or a OnSerializeNetworkView function.
The problem with using an RPC is you pass the data using arguments. My data includes arrays of classes so using an RPC is problematic.
I can use instead a OnSerializeNetworkView function and serialize the data into a stream. The problem with the current OnSerializeNetworkView function is you can't control when exactly it gets called. OnSerializeNetworkView is meant to be called continuously, and has to be attached to a certain Network View.
I need a Serialize function that would get called only when I tell it to, much like an RPC.
Having worked with the Torque Game Engine, Torque has what they call a NetEvent, basically a one-shot serialized data transmission from/to Server and Client.
This is perfect for initializing the Client with data, or when the Client needs to submit a list of information to the Server (like when buying/selling multiple items from/to a shop).
And please, if this gets implemented, please make it available to the Unity free version.
My guess is allowing a BitStream to be a valid argument to pass in an RPC is the most straightforward way to do this.
Right now I'm faking serialization by turning my data into one long string and sending that to the client. This, I guess, takes up a lot of bandwidth since strings in Mono are 16-bit each character because of Unicode support.

That's ok, I tell myself. Just imagine the client is loading a web page. Heck, maybe even the average web page is larger than what I'm transmitting. And I'm not sending it every loop or something; its for initializing client data, so a one-time, large bulk of data transmission is quite allowable.

It makes me miss my days when coding in Torque Game Engine. You can squeeze all the bits of data you want as small as possible there. They have their own version of the BitStream: Like a normal stream you serialize your data, but the special thing is the compactness of the serialization. Transmitting a boolean requires only one bit, strings can be compressed to save space, and you can specify by how much bits an integer or float is going to take when serialized into the stream.

For example, say you have an integer variable health, which in your game goes only in the range 0 to 100. You can then specify the health variable to be serialized to only 7 bits (essentially creating a 7 bit integer, which goes in the range 0-127), since its value goes only up to 100. You saved 25 bits, assuming it was a 32-bit integer, a whopping 78% of the original size.

They even have what they call a StringTableEntry. Basically used for strings that get sent over the network frequently, like usernames or preset error messages. What happens is the first time its sent, it gets sent as a normal string, but the next time, it gets sent only by a reference ID number to save bandwidth.

Saturday, June 5, 2010

Death Zone Zero: Minor Update: Syntax Errors Galore

I'm currently transitioning my code from Unityscript (Javascript) to C#. C# has its own quirks but nothing unmanageable. I figured I need C# because C++ plugins only work in C# via Dllimport. It'll be a very long time before I can use C++ plugins though (needs Unity Pro), but its better to do the conversion to C# sooner than later.

C# certainly has a stricter syntax compared to Unityscript and allowed me to catch some bugs that otherwise slipped by me in Unityscript.

C# also has preprocessor directives (something Unityscript doesn't have), which I need to use. Unityscript also has preprocessor directives.

I find C#'s typecasting more readable than Unityscript's.

Photobucket

Monday, May 10, 2010

Death Zone Zero: Minor Update: Bullet Ricochet Test

In this post I show a work-in-progress of the Gunslinger unit's special ability to make his shots ricochet off walls. Its kinda like in billiards games where you see the potential trajectory your ball will make before you make a shot.



I got my inspiration for this from Metal Gear Solid 1 where you fight Revolver Ocelot and his bullet shots would ricochet off the walls.

Saturday, May 8, 2010

Retrieving player's ranking in MySQL

Here's a neat little trick I figured out for myself when I was coding in MySQL. How to retrieve a player's current rank in a Leaderboards sort-of table.

-- this will calculate our current rank
SELECT count(DISTINCT exp) AS rank FROM player WHERE (exp > $exp);

-- this will retrieve 3 players that are of greater rank than us
SELECT * FROM player WHERE (exp > $exp) ORDER BY exp, username ASC LIMIT 3

-- this will retrieve 3 players that are of lower rank than us (or equal rank)
SELECT * FROM player WHERE (exp <= $exp) && (username != '$username') ORDER BY exp DESC LIMIT 3

-- top ten players
SELECT * FROM player ORDER BY exp DESC LIMIT 10

My example code comes from a PHP environment so $exp is a variable storing the selected player's current experience points, which in this example determines his rank. The greater one's experience points, the greater his rank. $username is a variable storing the selected player's unique username.

Sunday, April 25, 2010

Strategy RPG Test AI Planning

I've finally thought of a way to add AI in the Strategy RPG Test. Taking inspiration from the tactics feature in Dragon Age: Origins, each unit's AI would have a list of conditions and corresponding actions, for example, I would set the condition as "if the unit has less than 50% HP" and the corresponding action as "flee from enemies".



The list would be prioritized, in that higher conditions get activated first before lower ones. Lower conditions would be "if enemy in sight", "attack enemy", and then a final fallback action that gets executed without any condition needed like "search for enemies".

That list of conditions and actions would be defined in an XML file and then loaded into the game.

I guess this is why it pays off to play games, you get to study and understand how they work.

I had fun playing Dragon Age: Origins by the way. I played as a Human Male Arcane Warrior.

Photobucket

Friday, April 23, 2010

Grenade Skill Update

Photobucket
http://anomalousunderdog.herobo.com/Unity/DZZPrototype.html

The grenade deals damage (in a spherical area) and it has its own icon now. Some bug fixes here and there. Still missing are some explosion particle effects, sound effects, and a "throw grenade" animation.

Thursday, April 22, 2010

Grenade skill work-in-progress

I just found out that I have a wisdom tooth growing. I've never heard of wisdom teeth until now. It hurts; the pain is tolerable but irritating. Apparently it needs to be taken out using surgery. Why do teeth have to be so difficult to manage...

Anyway, in this update, here's a work-in-progress of the Throw Grenade skill, which is supposed to be used by the Army Private unit, of which I don't have a 3d model yet. So, I just added it as another skill for the Rifleman for now.

Photobucket
http://anomalousunderdog.herobo.com/Unity/DZZPrototype.html

Its still a work in progress, there's no icon for it yet, using the skill doesn't do anything besides launching the grenade (which is only a sphere for now); it doesn't do damage yet.

Well, its 3 AM, I'm hungry and I need to sleep. I better go.