Lesson 61 - OOP Enemy Classes Continued

Tutorial Series: Introduction to Unity with C# Series

Previous Article  |  Next Article


So let's just continue and power through the rest of our enemies that inherit from the Enemy class. So we're going to want a Gigantor, which will be a giant enemy. In Start(), set its radius, so it’s Collider radius will be a bit larger. Set its transform.localScale much larger a Vector3, five units for x and y. We’ll also give it a greater gravity scale, so it's affected a little bit less by gravity. So two versus the default value of one, I believe. We’ll also want a reference to the CheeseHead for the direction for moving towards the CheeseHead. So we'll say cheeseHead, and then we'll find the GameObject and we’ll set the direction to… We’ll have a little ternary here, so we’ll say cheeseHead… Basically if it's to the left or to the right of the cheeseHead will determine it's moving toward the cheeseHead, the direction in other words. That’s how we’ll set the direction. Again, that squiggly so we’ll need a a protected override void MovementPattern(). It’s going to be really simple, Body.velocity, so we’ll need to put this in FixedUpdate() because we’re affecting velocity again. New Vector2, we’ll have the speed times direction. And pass in its y velocity. And in FixedUpdate, we’ll call this.

Now because the direction is specified in Start(), we actually don't need to specify direction at instantiation. So what we’ll want to do is make an overload for Initialize() in the base class to take in the two arguments we need for Gigantor. So we’ll say... We’ll have the same basic implementation but just take out the direction. And let's test in the EnemiesFactory. So I'm just going to temporarily comment this out so we can test out the Gigantor. We’ll say Enemy of type Gigantor call them the giantGeorge. We’ll say a new Enemy<Gigantor>(“GiantGeorge”). I’ll say get the ScriptComponent, run its Initialize() method, and we’ll run the overload of variant that has only the two arguments. So we’ll speed is 1… I don't like doing this on separate lines. So I’ll just do this again. Say speed: 1. Again, just temporarily want to test this out, so say 1, 1, 1.

And we’ll see if out Gigantor gets instantiated. Got to get rid of that curly brace. We’re not going to need this dummy anymore I don't think, so let's get rid of that. Right, we’ve got our Gigantor now. We’ll make another enemy, call it ghost. Then in Start(), remember this will be a ghost so we'll figure out how to handle this later, but we’ll know that it's not going to collide with much of anything other than our player. So we’ll figure that out later, but right now we'll just destroy the existing collider, and also want to destroy the RigidBody. And the Sprite, we’ll put the sorting order to 1, and the color, we’ll want some opacity on that, because it’s a ghost. So we’ll set the opacity to half, so 0.5f, and the scale we’ll go to the localScale and we’ll say new Vector3() and we’ll make it fairly large. For the movement pattern, we’ll kind of have it as we did in the previous project. So we’ll say protective override void MovementPattern(). Transform.position equals a Vector3.MoveTowards(), transformed position. We’ll find the CheeseHead and move towards it at this speed. We’ll call that in Update(), not FixedUpdate(), no physics stuff going on here so it's a void Update().

Here in EnemiesFactory, we’ll say Enemy of type Ghost, say ghostlyGayle. Initialize to these values. We also don't need the directions, so we'll use that overload like we did with the Gigantor enemy, say new Vector3(). Alright, try this out. We should have two ghosts now because we have to those two floor GameObjects. Now he's following us around. We'll make another enemy. Just to show the benefits code reuse, we're going to have quite a few enemies here. A couple more anyways. We’ll say we have a Lush enemy. A lot of this code is going to have to do with this enemy's movement, so it’s not too easy to explain what's going on here. I kind of messed around until I got a sort of wobbling motion. That's what my aim was here, so I'm just going to construct this Lush enemy, and you'll see how it behaves later. And use this method WorldToViewpoint, again, to determine part of its motion. Return a Vector3, this will access the X value. If it’s greater than 0.5 so basically if it’s on the right of the middle or the left of the middle, to determine its direction. So direction = -1, else direction equals 1. Could easily make these into a ternary, maybe you’d want to do that on your end. I thought it’d kind of end up in a long line so I’m doing it this way. And in Update() we’ll have a timer functionality that will change its wobble width basically. So we’ll say if (Timer < maxwobblewidth/2)="" horizontalmotion="1." don't="" have="" to="" say="" one,="" but="" so="" it="" looks="" visually="" more="" appealing,="" i’ll="" use="" that="" as="" a="" multiplier.="" if(timer="">< maxwobblewidth),="" so="" if="" iit's="" not="" that="" amount,="" but="" less.="" nonetheless.="" no="" pun="" intended.="" i’m="" full="" of="" unintended="" puns="" aren’t="" i?="" horizontalmotion="-1" times="" direction.="" else="" if="" (timer=""> MaxWobbleWidth) Timer = 0.

We’ll set timer here as Time.deltaTime times sixty. And we’ll want protected override void MovementPattern(). Sort of use something like inertial force here. So we’ll say Body.AddForce, say new Vector2() HorizontalMotion times Speed for X. We’ll pass in the Y velocity. We’ll say ForceMode2D.Force. I’ll write a comment: Cap inertial motion speed. So this was sort of the effect of the GameObject sort of sliding as if on ice, something like that. So if (Body.velocity.x < speed="" 2*="" -1),="" we’ll="" say="" body.velocity="new" vector2()="" speed="" divided="" by="" 2="" times="" -1.="" and="" again,="" we’ll="" pass="" in="" the="" y.="" if(body.velocity.x=""> Speed/2) then Body.velocity = new Vector2(), Speed/2, pass in the velocity for Y.

And then call this in FixedUpdate, so void FixedUpdate, then we’ll instantiate this in the EnemiesFactory. We’ll say Enemy type Lush, call her a lushyLinda. And we’ll say she has random speed, so unpredictable lushyLinda. Seems appropriate somehow. And position. Alright, let's see what lushyLinda is like. Trying to get out of the way of lushyLinda, let her play around wobbling around and everything, there’s little wobbling lushyLinda. Alright, let's move on to the next enemy. Call this one Torque. Part of all these different enemies is also to show you some different physics methods available to you. So with Torque, we’ll actually be using torque. So Torque is an enemy, and in Start() we’ll just set its collider. Set its MovementPattern() right there, say it’s protected override void MovementPattern(). As I mentioned, we’ll be using the torque method called AddTorque() for this GameObject’s movement. So say if (Body.velocit.y < 0).="" so="" basically,="" it’s="" moving="" downwsrds.="" bodyaddtorque(),="" like="" a="" wheel="" basically.="" speed="" divided="" by="" two="" times="" direction.="" and="" i’m="" going="" to="" cast="" it="" to="" float="" to="" make="" sure="" we="" get="" a="" float="" out="" of="" that="" and="" not="" an="" integer,="" which="" will="" truncate="" important="" decimal="" values.="" so="" else="" if(body.velocity.y="=" 0).="" basically="" if="" it="" hit="" the="" ground,="" we’ll="" give="" it="" addforce()="" upwards.="" so="" for="" that,="" one="" hundred.="">

And we'll call that here and in EnemiesFactory, again we’ll test this out, call torqyTom and initialize it. We're going to need direction for this one, because we didn’t set it in the class. So torqyTom, we’ll call its Initialize() method. Set its speed to 3, its direction randomly will be set at instantiation.Random. Range(0,2) * 2 – 1. That gives minus one or one for direction. And we’ll set these positions to something more specific when we deal with this in a later lesson, the actual instantiation of these objects for a game not just for testing. So it’ll be torqyTom. Basically like a wheel gone loose spiraling towards our CheeseHead.

I think we have one more enemy we're going to create, it's going to be called Tweaker. This guy is going to be pretty unpredictable, the most unpredictable of this bunch. Tweaker is going to be an enemy, and it's going to need a Timer. And public bool, I don’t know if this needs to be public or not. So we can see it in the inspector. In Start(), we’ll set its Collider.radius, and its material color, it’s going to be yellowish. It’s a yellowish eyeball. And in Update(), we’ll have this change the Timer. This will reset the Timer every thirty ticks and make TweakOut true. We’re going to want a protected override MovementPattern(), we’ll say if TweakOut is true, we’ll have a random X and Y which we’ll create here in a local variable. randomX = Random.Range(-29f,29f). For Y, and the range will be a little more pronounced.

It doesn't know if we're using the Random method from UnityEngine or System, so either prefix UnityEngine before these calls to these methods, or we just get rid of system here. I don't think we’ll need it. So we'll say Body.AddForce() new Vector2 with randomX times speed, whatever that ends up being. randomY times speed, and then we'll make TweakOut false till it tweaks out again. As we know it will with the timer, it will become true again every thirty ticks. And in FixedUpdate() call this MovementPattern(). Enemy of type Tweaker, call him tweakyTim. Tim the Tweaker. Equals new Enemy Tweaker, and initialize. It's going be a fairly fast character, unpredictable and fast. Say speed and position. Alright, let’s check out Tweaky Time. Yep, all over the place.

Related Articles in this Tutorial:

Lesson 1 - Who This Course is For

Lesson 2 - What to Expect from this Course

Lesson 3 - Installation and Getting Started

Lesson 4 - Starting the First Project

Lesson 5 - Prototype Workflow

Lesson 6 - Basic Code Review

Lesson 7 - Game Loop Primer

Lesson 8 - Prototyping Continued

Lesson 9 - C# Fundamentals and Hello World

Lesson 10 - Variables and Operations

Lesson 11 - Variables and Operations Continued

Lesson 12 - Floats, Bools and Casting

Lesson 13 - If Statement Conditionals

Lesson 14 - If Statements Continued

Lesson 15 - Complex Evaluations and States

Lesson 16 - Code Syntax vs. Style

Lesson 17 - Variable Scope

Lesson 18 - Object-Oriented Programming Intro

Lesson 19 - OOP, Access Modifiers, Instantiation

Lesson 20 - Object Containment and Method Returns

Lesson 21 - "Has-A" Object Containment

Lesson 22 - "Is-A" Inheritance Containment

Lesson 23 - Static Fields and Methods

Lesson 24 - Method Inputs and Returns

Lesson 25 - Reference vs. Value Types

Lesson 26 - Introduction to Polymorphism

Lesson 27 - Navigating the Unity API

Lesson 28 - Applying What You've Learned and Refactoring

Lesson 29 - Constructors, Local Variables in the Update Method

Lesson 30 - Collecting Collectibles, Items and Powerups

Lesson 31 - Spawning and Managing Prefab Powerups

Lesson 32 - Implementing Powerup State Logic

Lesson 33 - Displaying Text, OnGUI, Method Overloading

Lesson 34 - Referencing Instantiated GameObjects, Parenting

Lesson 35 - Understanding the Lerp Method

Lesson 36 - Creating Pseudo Animations in Code

Lesson 37 - Understanding Generic Classes and Methods

Lesson 38 - Animations Using SpriteSheets and Animator

Lesson 39 - Working with Arrays and Loops

Lesson 40 - Debugging Unity Projects with Visual Studio

Lesson 41 - Camera Movement and LateUpdate

Lesson 42 - Playing Audio Clips

Lesson 43 - Routing Audio, Mixers and Effects

Lesson 44 - Adding Scoring Mechanics and Enhancements

Lesson 45 - Scene Loading and Game Over Manager

Lesson 46 - Understanding Properties

Lesson 47 - Controller Mapping and Input Manager

Lesson 48 - Understanding Enums

Lesson 49 - Dealing with Null References

Lesson 50 - Handling Variable Framerates with time.DeltaTime

Lesson 51 - Preparing the Project for Final Build

Lesson 52 - Final Build and Project Settings

Lesson 53 - Introduction to the Unity Physics Engine

Lesson 54 - Understanding FixedUpdate vs. Update

Lesson 55 - Movement Using Physics

Lesson 56 - Attack Script and Collision Events with OnCollisionEnter2D

Lesson 57 - Projectiles and Stomping Attack

Lesson 58 - Parallax Background and Scrolling Camera

Lesson 59 - Infinitely Tiling Background Sprites

Lesson 60 - OOP Enemy Classes

Lesson 61 - OOP Enemy Classes Continued

Lesson 62 - Trigger Colliders and Causing Damage

Lesson 63 - Multi-Dimensional Arrays and Procedural Platforms

Lesson 64 - Finishing Touches

Lesson 65 - Series Wrap


Please login or register to add a comment