Youtube Channel | Website
Unreal Sed [IDE]: UDK Thread | UT2004 Thread | UT3 Thread | Supports: UDK and all the games in the Unreal series.
UT2004: UT3 Viper for UT2004 | Heal Link Gun for UT2004 | UT3 Nightshade for UT2004 | UT3 Goliath for UT2004 | UT3 Manta for UT2004 | UT3 Raptor for UT2004 | UT3 Paladin for UT2004 | UT2004 Initor
UT3: Heal Link Gun for UT3 [PC] [PS3] | UT3 INI Color Tweak | Essence Link Gun for UT3 [PC] [PS3]
I don't see why anyone would want to use C++? Unrealscript is a simple and powerful language when used right. I originally came from actionscript 3 and no problem adapting to unrealscript at all. In fact, if Epic changed over to C++, more and more people would probably become even more scared of programming. C++ is a messy language, heck to even fully understand it you'd have to firstly learn C.
Games are programmed in C++, this is an almost universal truth. The switch to it means "real" game developers don't have to learn a new language just to start making games. Executing equivalent code in C++ over UnrealScript also means significant improvements in speed (in the order of 20-30 times faster).
You don't have to learn C first. I've never learnt 'C'.
- Please do not send me questions regarding programming or implementing things in UDK via Private Message. I do not have time to respond and they are much better answered in the forums. -
I don't think you need to fully understand C++ for gameplay programming.
Knowledge should be shared with everyone. Technique however, is your own thing.
My UnrealScript Lessons
My Blog
I'm working full-time, so I'm not available for freelance work, sorry.
You don't need to learn C first, you don't need to understand everything about it (I really doubt that there's a person that mastered it 100% to be honest), that doesn't change the fact that C++ is way too complex for gameplay design. Its too easy to screw things up with it.
I'm not saying it can't be used, its just that its not that practical to use when compared to interpreted high level languages. I'm guessing this is what Derp actually meant.
I don't see how C++ is better for gameplaydesign at all. You don't need this kind of performance for gameplay code. The reason C++, C and assembly are used for games is because performance is crucial when it comes to rendering algorithms. But for gameplay, I suppose that a garbage collected and interpreted language is actually more convenient. The only thing I miss in UC/Java/AS is call by reference.
I'd personally prefer continuing to work in UnrealScript for gameplay, however it's hard to ignore that there are plenty of compelling reasons to make a switch. I personally wouldn't mind working in C#.
- Please do not send me questions regarding programming or implementing things in UDK via Private Message. I do not have time to respond and they are much better answered in the forums. -
UnrealScript's abstraction degree is what makes it so powerful. It's intuitive to write code in it, you don't need to care about networking yourself, don't need to worry too much about manual garbage collection, have an easily understandable concept of states. Why give all those advantages up?
Our Loop, which art in source code, hallowed be thy keyword.
Thy condition come, thy instruction be done, in RAM as it is in cache.
Increment us this day our daily counter,
and forgive us our typos, as we also have forgiven our compilers.
And lead us not to the nullpointer but deliver us from bugs.
For thine is the API, the GUI, and the CLI while(true).
Semicolon;Please don't send me questions about how to do something in the UDK via PM. That is better discussed in the forums and we only have limited PM storage.
yes id be sad if they switched to C++, though I think something like unity does with C# might be cool. Would it improve performance to use C#? Also, isnt there a way for people to use C++ for gameplay coding now if they wanted to? If not, they could just implement that and have both Unrealscript and C++ be useable, depending on what you want to use.

Personally I don't see why UnrealScript as a source language should be replaced. The whys for that have already been pointed out.
What definitely needs replacement is what UnrealScript is compiled to. Any modern intermediate language is based on either a stack machine (e.g. Java's byte code, .NET's CIL) or a register machine (e.g. LLVM), whereas UnrealScript's bytecode is merely a binary representation of the text version. Some operations are directly mapped to opcodes (those without any declaration at all and those declared as native(number)), others aren't. One thing that strikes me as cumbersome is the way iterator and latent functions are implemented. Those must be native functions and they have strange effects. I think the iterators somehow create their own execution context (in the sense that the foreach block in state code doesn't really count as state code itself), while the latent functions really consist of two functions - one for the initial part and a second one executed each tick to check whether code execution may continue.
In Java the foreach loop is defined to iterate over any kind of array (UnrealScript does that as well already) and over any object implementing the Iterable interface. That interface does nothing more than specifying a function to return an Iterator object, which in turn specifies functions for retrieving the current value and step to the next value. The foreach loop is expanded by the compiler to request the Iterator object and step over its values, each time assigning the current value to the iteration variable.
In C# the situation is similar. Foreach can iterate over any object implementing the Enumerable or Enumerable<T> interface. Here arrays are not a special case, but in fact implement the interface. C# even expands on the concept by giving the programmer an implicit way to define an Enumerator or Enumerator<T> class. Any time a function returns either one of the Enumerable or Enumerator interfaces, C# allows you to write it as an iterator function. Instead of actually returning an Enumerator/Enumerable instance, you can use "yield return value" meaning "at this point the enumerator would return value" and optionally "yield break" meaning "the enumeration ends right here". The compiler constructs an anonymous iterator class that implements the Enumerator and optionally the Enumerable interface and contains a state machine to do what your function describes.
I have to admit that turning a function with "yield return/break" into an enumerator class is a non-trivial task for the compiler, but having custom iterator functions would be a really cool UnrealScript feature. Similarly I could imagine a way to describe latent functions in this way. Say, by declaring a function "latent" you are allowed to use some kind of pausing keyword to indicate that the state code should be halted for now. The next tick execution would return to the statement after the pausing keyword and code execution eventually either runs into "pause" again to stop execution or the function returns and goes to the next statement in state code.
Yes, those would be cool features, but I guess UE4 is too far into the development cycle already to do these things. They really only work if the language is compiled to a more powerful intermediate language than it is now. Suppose you wrote a function to return the sum of all players' scores:
Now in UnrealScript bytecode that would be structured as follows: (pseudo code based on UTPT "analyze raw" results, UT2004 version)Code:function float SumOfScores() { local int i; local float TotalScore; for (i = 0; i < GRI.PRIArray.Length; i++) { TotalScore += GRI.PRIArray[i].Score; } return TotalScore; }
Note the many levels of parentheses. UnrealScript bytecode must be interpreted in a recursive manner because opcode parameters may be other opcodes. In reality there are no parentheses in bytecode for most of the opcodes and instead the type, order and number of parameters is fixed. However, all function calls that have a declaration in UnrealScript source code need an EndOfParameters pseudo-opcode after the last parameter. That not only goes for functions implemented in script, but even for those that got their own opcode via native(number).Code:JL0000: Let(LocalVar(i), IntZero()) JL0007: JumpIfNot(JL004E, Less_IntInt(LocalVar(i), DynArrayLength(Context(InstanceVar(GRI), InstanceVar(PRIArray))))) JL0020: AddEquals_FloatFloat(LocalVar(TotalScore), DynArrayElement(LocalVar(i), Context(InstanceVar(GRI), Context(InstanceVar(PRIArray), InstanceVar(Score))))) JL0044: AddAdd_Int(LocalVar(i)) JL004B: Jump(JL0007) JL004E: Return(LocalVar(TotalScore)) Return(Nothing()) EndOfScript()
C# code on the other hand would be compiled to something like this: (actual CIL disassembly by ILSpy)
Really all opcodes have a defined number of parameters and they are all constants. The opcodes could be interpreted in a big loop without any recursion (except for real function calls, obviously).Code:.method public hidebysig instance float32 SumOfScores () cil managed { // Method begins at RVA 0x20d8 // Code size 53 (0x35) .maxstack 3 .locals init ( [0] float32 TotalScore, [1] int32 i ) IL_0000: ldc.r4 0.0 IL_0005: stloc.0 IL_0006: ldc.i4.0 IL_0007: stloc.1 IL_0008: br.s IL_0023 // loop start (head: IL_0023) IL_000a: ldloc.0 IL_000b: ldarg.0 IL_000c: ldfld class Test.GameReplicationInfo Test.Program::GRI IL_0011: ldfld class Test.PlayerReplicationInfo[] Test.GameReplicationInfo::PRIArray IL_0016: ldloc.1 IL_0017: ldelem.ref IL_0018: ldfld float32 Test.PlayerReplicationInfo::Score IL_001d: add IL_001e: stloc.0 IL_001f: ldloc.1 IL_0020: ldc.i4.1 IL_0021: add IL_0022: stloc.1 IL_0023: ldloc.1 IL_0024: ldarg.0 IL_0025: ldfld class Test.GameReplicationInfo Test.Program::GRI IL_002a: ldfld class Test.PlayerReplicationInfo[] Test.GameReplicationInfo::PRIArray IL_002f: ldlen IL_0030: conv.i4 IL_0031: blt.s IL_000a // end loop IL_0033: ldloc.0 IL_0034: ret } // end of method Program::SumOfScores
For example, IL_0023 to IL_0031 is the "i < GRI.PRIArray.Length" check. It works as follows:
- Push local variable 0 (i) into the stack.
- Push argument 0 (this/self) onto the stack.
- Pop reference off the stack (happens to be this/self) and load the instance referenced in that object's field (instance variable) "GRI" (which is a GameReplicationInfo) to push it onto the stack.
- Pop reference off the stack (the GRI instance) and load the instance referenced in that object's field "PRIArray" (an array of PlayerReplicationInfo objects) to push it onto the stack.
- Pop array reference off the stack (the PRIArray), find that array's length and push it onto the stack.
- Convert the top of stack (the array length) to a signed 32 bit integer. (because ldlen really returns an unsigned value)
- Pop two values off the stack and jump to position marked as "IL_000a" if the first one (local variable i) is less than the second one (GRI.PRIArray.Length).
The number of operations is similar to the UnrealScript version here, but the big advantage is that only values are pushed onto and popped off a data stack, there are no nested function calls to handle this stuff. This is already optimized code. If compiled in debug mode, there would be something like "clt" and "brtrue.s" instead, i.e. "compare if first is less than second" and "jump if true".
You may have noticed that "i++" is compiled as "i = i + 1" here, whereas it is compiled as "PostIncrement(i)" in UnrealScript. On the other hand, the CIL does not know the operators ||, && or ?:, it simply represents them with the various available conditional jump opcodes. UnrealScript needs special (and IMHO quite ugly) handling for those cases. There's a special "skip" opcode that is only evaluated in the || and && operator implementations. UnrealScript includes offsets in quite a number of instructions, e.g. the "Context" instruction for accessing members of other instances. The Context instruction is what produces the "Accessed None" warning and it needs to skip over the remaining code of that statement. This check could either be done explicitly in the bytecode (the number of required checks could be reduced via statistical code analysis) or via the various load/store operations.
Assume instructions "ldarg.0", "ldfld GRI" and "ldfld PRIArray" and the GRI variable being empty. "ldarg.0" pushes "self", "ldfld GRI" pops "self" and pushes "none". In .NET the "ldfld PRIArray" would see the null reference and throw a NullReferenceException. In the Unreal Engine it would instead log "Accessed None" and push "none" again. A following "ldlen" or "ldelem" instruction would perform similar fallback behavior. Or, to reduce log spam, the first error could push some error reference value instead to signal following instructions that the problem is already known.
tl;dr version:
It would be cool if current UnrealScript interpreter is dumped in favor of a JVM- or CLR-style interpreter with corresponding style of bytecode.
I remember there were thoughts about a JIT compiler for UnrealScript bytecode. Something like that might be easier to implement if the bytecode wouldn't need as much special handling as it does now.
Also, .NET, Java and others can't be used directly because graceful handling of exceptions is required. UnrealScript does not have any exception handling and instead defaults for standard values. If something goes wrong there's a warning in the log and values such as 0, "", None or False are used.
Wormbo's UT/UT2004/UT3 mods | PlanetJailbreak | Unreal Wiki | Liandri Archives
- Everything you ever wanted to know about replication (but were afraid to ask) [also in German]
- UnrealScript security considerations
Note that your questions via PMs will be ignored if they actually belong in the forum.<elmuerte> you shouldn't do all-nighters, it's a waste of time and effort
<TNSe> nono
<TNSe> its always funny to find code a week later you dont even remember writing
<Pfhoenix> what's worse is when you have a Star Wars moment
<Pfhoenix> "Luke! I am your code!" "No! Impossible! It can't be!"
From a design point of view, using C++ as gameplay programming language is a huge step back from UScript. Unreal Engine has always been about putting as much control in the hands of designers and artists as possible. And i expect Epic to expand upon this concept with seamless transition of visual scripting and coding. Combining a UScript like language and Kismet into one interface for example.
Just for the sake of it, here's a real bytecode representation:
Decompiled with my own UnrealScript decompiler UE ExplorerCode:(0x000) DebugInfoToken(14) (0x00E) DebugInfoToken(14) (0x01C) LetToken(11) -> LocalVariableToken(9) -> IntZeroToken(1) I = 0 (0x027) DebugInfoToken(14) (0x035) JumpIfNotToken(80) -> NativeFunctionToken(77) -> LocalVariableToken(9) -> DynamicArrayLengthToken(52) -> ContextToken(51) -> ContextToken(30) -> InstanceVariableToken(9) -> InstanceVariableToken(9) -> InstanceVariableToken(9) -> EndFunctionParmsToken(1) if(I < WorldInfo.GRI.PRIArray.Length) (0x077) DebugInfoToken(14) (0x085) NativeFunctionToken(107) -> LocalVariableToken(9) -> ContextToken(82) -> DynamicArrayElementToken(61) -> LocalVariableToken(9) -> ContextToken(51) -> ContextToken(30) -> InstanceVariableToken(9) -> InstanceVariableToken(9) -> InstanceVariableToken(9) -> InstanceVariableToken(9) -> EndFunctionParmsToken(1) TotalScore += WorldInfo.GRI.PRIArray[I].Score (0x0E2) DebugInfoToken(14) (0x0F0) DebugInfoToken(14) (0x0FE) NativeFunctionToken(25) -> LocalVariableToken(9) -> EndFunctionParmsToken(1) ++ I (0x109) DebugInfoToken(14) (0x117) JumpToken(3) goto J0x27 (0x11A) DebugInfoToken(14) (0x128) ReturnToken(10) -> LocalVariableToken(9) return TotalScore (0x132) DebugInfoToken(14) (0x140) DebugInfoToken(14) (0x14E) ReturnToken(10) -> ReturnNothingToken(9) return ReturnValue (0x158) DebugInfoToken(14) (0x166) EndOfScriptToken(1)![]()
EliotVU.com
UT2004: MutNoAutoFire / LevelConfigManager / MutBestTimes / MutCacheExtractor / MutHalloween
UT3: MutDodgeJump / MutXMasPresents
UDK: UE Explorer / Forms
Just came across this : http://gameindustry.about.com/od/tre...First-Look.htm
So unrealscript is finished?
How did they come to that conclusion? Wired's article doesn't even contain the word "UnrealScript".
Knowledge should be shared with everyone. Technique however, is your own thing.
My UnrealScript Lessons
My Blog
I'm working full-time, so I'm not available for freelance work, sorry.
There are skills you learn with UnrealScript that should be transferrable as learning kismet can open your eyes to some UScript as well since the terminology is similar if not the same. Im hoping that people who have only started with UScript will be able to make the transition to C++ or Kismet2 easily.
Epic Flaming Olympus Lvl1 | Alien Abduction Survivor | Round 1, Fight! | Conga! How low can ya go | Damn sandworms! | Got UnrealScript skills?
BeyondUnreal Wiki
There's no formula for fun
@MonsOlympus, i think it will be quite easy for people to switch to C++ it's known and used everywhere there are loads of tutorials out there and it's used everywhere, i prefer unrealscript but if epic decided against it then there is nothing i can do about it,
http://www.myclodel.com/ Is IRC Channel
Tutorials on what though? As a language c++ is far more complex to deal with. I'm going to assume Epic has their own libraries which won't have any unofficial documentation. Unreal script on the other hand has a wealth of information from a variety of sources. I just feel once UE4 hits I'll be unable to give the level of support in the programming forums because c++ has such a wide scope and more nuances than a dead horse.
Epic Flaming Olympus Lvl1 | Alien Abduction Survivor | Round 1, Fight! | Conga! How low can ya go | Damn sandworms! | Got UnrealScript skills?
BeyondUnreal Wiki
There's no formula for fun
Using C++ does have its benefits. Learning C++ will open up far more doors for a programmer than Unrealscript would. (Thinking outside the box!)
@MonsOlympus, yeah i agree you are right it will change alot of things when it will come out, but hopefully it will come out in a few years time not a few weeks
@Derp, you might be right but like MonsOlympus said c++ is far more complex than unrealscript when people will ask questions on forums alot of people will be confused it will be really hard to answer,
http://www.myclodel.com/ Is IRC Channel
Pros and cons from my point of view.
The pros are the speed and flexibility of C++, as well as it being a fairly mature well defined language.
The cons are that i'm going to miss the states in unrealscript - they are a really neat feature. Also the potential for memory leaks and subtle pointer errors which can be difficult to find.
My other concern is regarding source code. Currently it seems that all the unrealscript it is fully available, however they hide the native implementation. What happens when it's all C++? Are they going to release a big chunk of that code so that we can learn from example - as we currently do with unrealscript?
@Paco that's a good question i wonder how they would do it,
http://www.myclodel.com/ Is IRC Channel
Agreed.
States ws a powerful feature. To do that in C++ you will have to use nasty switch-cases.
But I strongly believe Epic will create some library to make this easier for us (like MFC or Win32...). Still pointers and memory leeks? That is a serious issue. Personally I like C/C++ but for a game engine its too much headache. I could not imagine an engine without a scripting language.
- Please do not send me questions regarding programming or implementing things in UDK via Private Message. I do not have time to respond and they are much better answered in the forums. -
Well, colour me shocked. I wouldnt have thought uscript would be dropped, but there it is. It would be nice if things are abstracted for us. There was discussion about memory leaks, usually caused by new and delete not being called in equal amounts. Could this be mitigated if there is an API that handles the states, spawning and destruction. So all the same features that unrealscript has. Doesn't unrealscript expand from c++ anyway (the native code blocks look like c++)?
I will be interested to see how the cross device compatibility works with c++ dlls. Maybe you end up with a dll for each machine? Also very excited about the idea of in game editing in real time! That alone would be worth the switch.
What I think must be in Unreal Engine 4 (Scripting part):
1)Easy saves. I.e bool QuickSave(string nm,optional string level) function. Which saves all project. And bool QuickLoad(string nm,optional string level) .
If someone want more complex solution, he can write save code manually, but quick solution will be very useful.
Level parameter is for open world games where returning to old level loads it in old state.
2)PreloadMap(string map) for begin preloading maps (and next start map console command will be very fast).
I.e. when Player location is near end, you can run PreloadMap with all maps which can be loaded.
3)Flash movie interface will be removed (or only will be used for cutscenes/movies for cartoon projects).
Building interface with help of flash very strange decision.
4)Kismet will be removed. I think that standard text programming language much better even for map related events.
In this forum someone posted the picture with thousand links! This is not good.
Maybe some pair like Java/JavaScript must be used.
5)Map change function takes some Object pointer, with all important information (Score, Health etc.).
It is very strange to Save/Load data for this purposes.
6)More easy change of loading movie - program can specify movie (optional) for each map change.
7)Build in dialogs for standard save/load/settings etc. will be useful too.
99% of games has identical dialogs and very strange when all teams must do it.
8)Some script wizard like: http://www.bludnikov.ru/eng.htm.
9)Standard "Create character dialog" where player can customize his hero (customization of the modular pawn). For any pawn this feature can be used in editor. Game designer/programmer can change meshes/materials for different races and can select races for hero.
10)DamageType must changed: now class is abstract and there is problems for RPG (where spell can has some effects with different power).
Last edited by rquester; 05-24-2012 at 10:26 AM.
Lol wow?Kismet will be removed. I think that standard text programming language much better even for map related events.
Unreal Engine 2 and 1 used strings for events, it was hard to track and a huge pain in the rear. Key frames had to be entered by right clicking for movers and generally was a pain to set up. You also had to remember event names and which one had event names. Kismet and Kismet 2 will be great.
A script wizard will be useless, why do you keep advertising that thing.
For movies you can detect which map is going to be loaded and load the proper movie. Everything after that is pointless. That's why you make the game and features you want in yourself. If Epic added every feature for every possible game it would just turn into a bloated software.
In the end I'm looking forward for the change, I enjoy learning and this will just pull me away from a scripting language and put me in the realm of a much more used language in the programming world.
Last edited by TheAgent; 05-24-2012 at 10:59 AM.
FREELANCER PROGRAMMER/ARTIST OPEN FOR HIRE
Tutorial :
Vaulting Using Actors
Widescreen Hotfix (Canvas)
Scene Contrast PostProcess
Creating Menus/Buttons Using Canvas
RPG Inventory Abstract
Ocean Waves using World Position Offset
Sniper Lens Effect
Packs/Downloads :
BallGame Starter Pack
Zombies Demo/Source Code
Please do not PM me with questions. I am very busy and questions are better off left to the forums. Thank You
Spoof
So strange that almost all AAA engines and games use it? Scaleform Flash isn't going anywhere.
Scaleform is not comfortable for programming, slow and needs a not a free tool. Additional language isn't good too... AAA titles use Scaleform only as advertised replacement for canvas. In real projects Scaleform doesn't give anything. Excluding very specific games with cartoon movies.
And Kismet2 was already announced.
Maybe it will not like Kismet1 and will use ordinary script language?
TheAgent
Unreal Engine 2 and 1 used strings for events
If Unreal 1 has bad text language realization, then it is not mean that another realization will bad too.
In real, Kismet programs more then 50 nodes isn't supportable, because too many links.
A script wizard will be useless, why do you keep advertising that thing.
Maybe it is not perfect, but something like it needs anyway. 200K of text for basic program - it isn't good. I'll make script wizard because write too many code in each program isn't good.
or movies you can detect which map is going to be loaded and load the proper movie.
This isn't optimal way. And I didn't found documentation for it...
That's why you make the game and features you want in yourself. If Epic added every feature for every possible game it would just turn into a bloated software.
Load/Save, menu, settings dialog and many other things is main features, which need in 99% of the games.
Pawn customization is easy thing (because modular pawns already in UDK) too, which can save many working hour.
Last edited by rquester; 05-24-2012 at 11:45 AM.
If you can't keep your Kismet tidy then you're doing it wrong. Visual scripting systems are easier to grasp by non-technical people. Whether you like it or not, it's a fact. Kismet is not going away, on the contrary. That was quite clear in Wired's article.
Knowledge should be shared with everyone. Technique however, is your own thing.
My UnrealScript Lessons
My Blog
I'm working full-time, so I'm not available for freelance work, sorry.
Mougli
If you can't keep your Kismet tidy then you're doing it wrong.
Even examples (Jazz game) isn't clean.
Visual scripting systems are easier to grasp by non-technical people.
If they begin to use conditional statements, functions and variables then is not.
Maybe script language with something Wizard (designer selects from menu lines like "button to call elevator", "door open" etc.) will be better.
I've had more than 80 kismet nodes kept it clean and it ran perfectly fine. TO be honest Kismet 2 will probably be even better.
FREELANCER PROGRAMMER/ARTIST OPEN FOR HIRE
Tutorial :
Vaulting Using Actors
Widescreen Hotfix (Canvas)
Scene Contrast PostProcess
Creating Menus/Buttons Using Canvas
RPG Inventory Abstract
Ocean Waves using World Position Offset
Sniper Lens Effect
Packs/Downloads :
BallGame Starter Pack
Zombies Demo/Source Code
Please do not PM me with questions. I am very busy and questions are better off left to the forums. Thank You
I don't use Kismet often but when i do some codes i notice that sometimes kismet is needed and it's really useful for one-level simple codes, so to be honest Kismet should not be removed,
http://www.myclodel.com/ Is IRC Channel
TheAgent
I've had more than 80 kismet nodes kept it clean and it ran perfectly fine. TO be honest Kismet 2 will probably be even better.
Only if on the level works one person and without long inactivity period. And 80 lines of code is a very small and simple program.
reinrag
I don't use Kismet often but when i do some codes i notice that sometimes kismet is needed and it's really useful for one-level simple codes, so to be honest Kismet should not be removed,
Some level-based script in that simple cases will be more simple. With special wizard - much more simple for beginners.
Spoof
25 years experience in this industry is telling me that this thread is no longer worth the effort.
Why? Because you agree with all items?
80 NODES, not lines of code, clearly you don't know what you are talking about. I've written thousands of lines of code. I'm just feeling some incompetence here. Good luck.
FREELANCER PROGRAMMER/ARTIST OPEN FOR HIRE
Tutorial :
Vaulting Using Actors
Widescreen Hotfix (Canvas)
Scene Contrast PostProcess
Creating Menus/Buttons Using Canvas
RPG Inventory Abstract
Ocean Waves using World Position Offset
Sniper Lens Effect
Packs/Downloads :
BallGame Starter Pack
Zombies Demo/Source Code
Please do not PM me with questions. I am very busy and questions are better off left to the forums. Thank You
Bookmarks