Consider the following domain concepts:
Input Handler (represented by a concrete class InputHandler; handles user input)
Attack (depends on user input and used when handling input; HAS AN Attack Effect)
Attack Effect (is dependent on the runtime user input)
Some possible usage scenario in InputHandler (pseudo):
someAttackInstance.ApplyEffect(someInputDerivedData)
Given that I don't expect to have different implementations for Attacks, is it recommended to have:
InputHandler depending on an Abstract Factory (IAttackFactory) for instantiating Attacks
IAttackFactory depending on an Abstract Factory (IAttackEffectFactory) for instantiating Attack Effects
IAttackEffectFactory defining a method Create(SomeInputData) to create effects
Update:
Here is some more information:
InputHandler: a class that detects mouse events (left click, right click) and keyboard events (whether Ctrl is pressed)
Attack: think showing an image of a bullet (left click => red bullet; right click => blue bullet)
AttackEffect: if Ctrl is pressed then we assign effect1 to the bullet, otherwise effect2. Assume an effect is applied to other objects. (How would a bullet affect a wall?)
Assume I want to use Dependency Injection, and pass dependencies in constructors. To instantiate an Attack instance, is it the recommended way to utilize an Abstract Factory IAttackFactory inside my InputHandler class and that IAttackFactory having an IAttackEffectFactory dependency for building effects for the attack?
Assuming InputHandler as root:
var bullet = attackFactory.CreateAttack(ctrlWasPressed);
bullet.Color = mouseButtonPressed == MouseButton.Right ? Color.blue : Color.Red;
in BulletAttackFactory:
ctor(IAttackEffectFactory fac){this.fac = fac;}
IAttack CreateAttack(bool ctrlPressed)
{
IAttackEffect eff = this.fac.CreateEffect();
IAttack att = new Attack(eff);
}
in BulletEffectFactory:
IAttackEffect CreateEffect(bool ctrlPressed)
{
if(ctrlPressed)
return new HighCaliberEffect();
return LowCaliberEffect();
}
Related
I am struggling to find a good tutorial or informations that would allow me to select multiple objects in 3D in a user friendly manner.
So far, the best tutorial I found is this one : https://sharpcoderblog.com/blog/unity-3d-rts-style-unit-selection. The tutorial works by using the transform.position of the selectable objects and checking if it within the user's selection.
What I wish is to have the user be able to select a unit even if it is only partially within the user's selection such as most RTS games do ( both in 2D and 3D ).
One possibility would be to create a temporary mesh using the camera's clipping distances and the user's selection and then check for collisions but I was not able to find any tutorials using this method nor do I know if it is the best approach to the subject.
If I understand correctly you want to
somehow start a selection
collect every object that was "hit" during the collection
somehow end the collection
Couldn't you simply use raycasting? I will assume simple mouse input for now but you could basically port this to whatever input you have.
// Just a little helper class for an event in the Inspector you can add listeners to
[SerializeField]
public class SelectionEvent : UnityEvent<HashSet<GameObject>> { }
public class SelectionController : MonoBehaviour
{
// Adjust via the Inspector and select layers that shall be selectable
[SerializeField] private LayerMask includeLayers;
// Add your custom callbacks here either via code or the Inspector
public SelectionEvent OnSelectionChanged;
// Collects the current selection
private HashSet<GameObject> selection = new HashSet<GameObject>();
// Stores the current Coroutine controlling he selection process
private Coroutine selectionRoutine;
// If possible already reference via the Inspector
[SerializeField] private Camera _mainCamera;
// Otherwise get it once on runtime
private void Awake ()
{
if(!_mainCamera) _mainCamera = Camera.main;
}
// Depending on how exactly you want to start and stop the selection
private void Update()
{
if(Input.GetMouseButtonDown(0))
{
StartSelection();
}
if(Input.GetMouseButtonUp(0))
{
EndSelection();
}
}
public void StartSelection()
{
// if there is already a selection running you don't wanr to start another one
if(selectionRoutine != null) return;
selectionRoutine = StartCoroutine (SelectionRoutine ());
}
public void EndSelection()
{
// If there is no selection running then you can't end one
if(selectionRoutine == null) return;
StopCoroutine (selectionRoutine);
selectionRoutine = null;
// Inform all listeners about the new selection
OnSelectionChanged.Invoke(new HashSet<GameObject>(selection);
}
private IEnumerator SelectionRoutine()
{
// Start with an empty selection
selection.Clear();
// This is ok in a Coroutine as long as you yield somewhere within it
while(true)
{
// Get the ray shooting forward from the camera at the mouse position
// for other inputs simply replace this according to your needs
var ray = _mainCamera.ScreenPointToRay(Input.mousePosition);
// Check if you hit any object
if(Physics.Raycast(ray, out var hit, layerMask = includeLayers ))
{
// If so Add it once to your selection
if(!selection.Contains(hit.gameObject)) selection.Add(hit.gameObject);
}
// IMPORTANT: Tells Unity to "pause" here, render this frame
// and continue from here in the next frame
// (without this your app would freeze in an endless loop!)
yield return null;
}
}
}
Ofcourse you could do it directly in Update in this example but I wanted to provide it in a way where you can easily exchange the input method according to your needs ;)
From UX side you additionally might want to call a second event like OnSelectionPreviewUpdate or something like this every time you add a new object to the selection in order to be able to e.g. visualize the selection outcome.
I might have understood this wrong and it sounds like you rather wanted to get everything inside of a drawn shape.
This is slightly more complex but here would be my idea for that:
Have a dummy selection Rigidbody object that by default is disabled and does nothing
don't even have a renderer on it but a mesh filter and mesh collider
while you "draw" create a mesh based on the input
then use Rigidbody.SweepTestAll in order to check if you hit anything with it
Typed on smartphone but I hope the idea gets clear
I think I would try to create a PolygonCollider2D because it is quite simple comparing to creating a mesh. You can set its path (outline) by giving it 2D points like location of your pointer/mouse. Use the SetPath method for it. You can then use one of its methods to check if another point in space overlaps with that collider shape.
While the PolygonCollider2D interacts with 2D components you can still use its Collider2D.OverlapPoint method to check positions/bounds of your 3D objects after translating it to 2D space.
You can also use its CreateMesh method to create a mesh for drawing your selection area on the screen.
You can read more about the PolygonCollider2D here.
Hope it makes sens and hope it helps.
Ok, so, a Slider in Unity has an "On Value Changed (Single)" property. As far as I've managed so far, you can set on it a callback function that can take a parameter (e.g. a string) which you hardcode in the Inspector, and/or a function that takes a float (the new value that the slider has been set to). However, I'd like to be able to pass both, and I haven't seen a way to do it. For example, I'd like to have a function saveValue(string name, float value), and several sliders feeding their values into it - each slider would have a different name written in the Inspector, and the updated value would be passed as value. I suspect Unity does not support that, but I haven't found any documentation explicitly describing this feature, so I'm not sure. Can this be done?
This should get you started:
Create a class that all of your sliders can access (for example by reference). And put the method you want them to call in there. The method should take the two parameters that you want to use (in my case I want it to take a GameObject and a float):
public class SliderManagerScript : MonoBehaviour
{
public void SliderValueChangeHandler(GameObject slider, float value)
{
Debug.Log("Slider name: " + slider.gameObject.transform.name);
Debug.Log("Slider value: " + value);
}
}
On each of the sliders that you want to call the above method, add a script that can access the above class and add an event listener for the Slider's onValueChanged property. Register a delegate for that listener which calls the method shown above and passes in the appropriate values. E.g
public class SliderScript : MonoBehaviour
{
public GameObject sliderManager;
void Start()
{
GetComponent<Slider>().onValueChanged.AddListener(delegate { sliderManager.GetComponent<SliderManagerScript>().SliderValueChangeHandler(this.gameObject, this.GetComponent<Slider>().value); });
}
}
And that should work fine. In fact, you should be able to simplify it a lot more depending on how you've architected your code.
I am trying to build a application which includes using leap motion interaction engine to move the object in unity 3d. However, i also need to find out which fingers are touching the object when interacting with object in unity. Is there anyway i can do that? Thanks in advance!!
Strictly speaking, the Grasping logic of the Interaction Engine has to check this very thing in order to initiate or release grasps, but it doesn't have a friendly API for accessing this information.
A more convenient way to express this, even though it's not the most efficient way, would be to detect when a hand is intersecting with the interaction object and checking the distance between each fingertip and the object.
All InteractionControllers that are intersecting with a given InteractionBehaviour can be accessed via its contactingControllers property; using the Query library included in Leap tools for Unity, you can convert a bunch of Interaction Controller references to a bunch of Leap Hands without too much effort, and then perform the check:
using Leap.Unity;
using Leap.Unity.Interaction;
using Leap.Unity.Query;
using UnityEngine;
public class QueryFingertips : MonoBehaviour {
public InteractionBehaviour intObj;
private Collider[] _collidersBuffer = new Collider[16];
private float _fingertipRadius = 0.01f; // 1 cm
void FixedUpdate() {
foreach (var contactingHand in intObj.contactingControllers
.Query()
.Select(controller => controller.intHand)
.Where(intHand => intHand != null)
.Select(intHand => intHand.leapHand)) {
foreach (var finger in contactingHand.Fingers) {
var fingertipPosition = finger.TipPosition.ToVector3();
// If the distance from the fingertip and the object is less
// than the 'fingertip radius', the fingertip is touching the object.
if (intObj.GetHoverDistance(fingertipPosition) < _fingertipRadius) {
Debug.Log("Found collision for fingertip: " + finger.Type);
}
}
}
}
}
In my Unity3D project I got a complex GameObject of a truck that his hierarchy looks like this.
+ Truck
+FrontPivotPoint
+LeftWheel
Tire
Rim
Hindge
+RightWheel
Tire
Rim
Hindge
+CenterPivotPoint
+Body
Arm
Screw
Pin
Basically what's happening is I got a lot of complex parenting and I want to go trough every child and add to him a RigidBody.
I think it should be something nested but I don't have something in mind.
Any help would be appreciated!
Unity3d allows you to easily automate every routine. You may consider to add custom menu item.
public class MakeRigidBodies : EditorWindow
{
[MenuItem ("Make rigid bodies %&r")]
private static void Execute()
{
var selectedObject = UnityEditor.Selection.activeObject;
if( selectedObject && selectedObject is GameObject )
{
// for all children of selectedObject
{
// add rigid body
}
}
}
}
From what I can see, the structure of your game objects is like a tree data structure. Truck as its parent / root node, and the others as its child. So, you must traverse all the objects / nodes in your structure with tree traversing algorithm, the best that I know is Depth-First-Search (DFS) algorithm.
DFS work like nested loop, the main algorithm are:
Start from the root node
Find its node children
Visit the child
Back to step 2 until all children is visited
This algorithm can be implemented in Unity3d since GameObject stores its child information in transform properties (see http://answers.unity3d.com/questions/416730/get-the-child-gameobject-of-a-parent-and-not-the-t.html). And last, we can add RigidBody to the GameObject with the AddComponent() method (see http://answers.unity3d.com/questions/19466/how-do-i-add-a-rigidbody-in-script.html).
Here is my script to answer your question:
using UnityEngine;
using System.Collections;
public class AddRigidBody : MonoBehaviour {
private void addRigidBody(GameObject gameObject)
{
Rigidbody rigidBody = gameObject.AddComponent<Rigidbody>();
foreach(Transform t in gameObject.transform)
{
addRigidBody(t.gameObject);
}
}
void Start () {
addRigidBody (this.gameObject);
}
}
This script attached to the parent / root GameObject. The AddRigidBody() method is called when this script start (as in Start() method), and this method will traverse all child and add a RigidBody through it.
If I'm not mistaken, and bear with me since it's been a while since I've worked with Unity3D, this could fix it:
* Drag your model onto the stage
* Your entire model should now be selected; parent and its underlying children
* Select the option to add a rigidbody and it should add it to all selected objects.
* Make a prefab of the model and you should be done.
Once again, don't trust me on this. It's been a while and since I don't have access to Unity3D right now, I am unable to check this method myself.
If it's the code approach you want, try this (C#, methods may vary for Boo or Java):
Getting a child: http://forum.unity3d.com/threads/get-child-c.83512/ (see second reply)
Adding a rigidbody: http://answers.unity3d.com/questions/19466/how-do-i-add-a-rigidbody-in-script.html
I hope this helps.
I'm learn as3, and building some exercises from the adobe online tutorials. I'm trying to do a very simple task and I think my code is exactly the same as the tutoriala nd it's not working! I just can't work it out...
I'm trying to change the textfield in a button from that buttons class.
The button is called GameButton, the textfield is called blabel and is classic text and dynamic text. Here is the code for the GameButton class. Instead of displaying "Click" as below it just changes the label to the number 1. The trace statement is working etc it is going there, but the text isn't passing through or something. Please help!!!
package {
import flash.display.MovieClip;
public class GameButton extends MovieClip {
public function GameButton() {
trace("Gamebutton has been created");
this.blabel.text = "Click";
stop();
}
}
}
The long and short of it is you can create the button in code, or else you can try listening for added to stage events coming from the parent object you're adding the children to (maybe the stage, maybe another DisplayObjectContainer). The problem with the listening method is I'm not sure how you would know which child just dispatched the event without making some messy code. I think the first option is generally easier and makes more sense, the only caveat is that you have to place the instances using x/y coordinates or apply scaleX, scaleY to stretch or shrink objects instead of doing it using the authoring tool. You can still use the drag and drop parts of flash to figure out coordinates and build individual movie clips etc.
Enough talk on to some code:
package
{
import flash.display.MovieClip;
public class GameButton extends MovieClip {
private var blabel:TextField; //This can be any display object class or a class that extends from a display object class (Sprite, MovieClip, MyCustomButton etc.)
public function GameButton() {
blabel = new TextField(); //The type after new, should be the same, or a sub-class (extension) of the type used in the variable declaration above
addChild(blabel);
//blabel.x=10; //optional over ten pixels from left
//blabel.y=10; //optional down ten pixels from top
//blabel.scaleX=.5; //optional half the width
//blabel.scaleY=2; //optional 2 times taller
trace("Gamebutton has been created");
blabel.text = "Click";
stop();
}
}
}