Basic C# Syntax & Knowing What Is Needed

No matter what the problem is or the goal is in your Unity Project, what is a good way to outline one’s desired effect in Unity using C#?

I know what I want to happen, but how do I tell the computer to do it?

*For Example, I am working on an Augmented Reality Project, if I wanted to touch an object and have it follow my finger as I rotate the camera with a gyroscope then have that object stay in place when I let go...  what are all of the pieces I need?
 - If my finger is held on an object for 1 second, attach object to screen position of camera.  Or would I make the object a child of the camera so it rotates with the camera?  Also, it would be nice to have the object perform a scale transform and scale up a little gradually during the 1 second.
 - Once Touch.Phase == Ended, that object will no longer transform or be a parent of the camera. (Depending on physics, it will remain stationary or fall.)*

*Another Example would be:  I want to swipe my screen in the upwards motion and transform the camera's or players position forward.
 - I need to get the Touch.Phase Began and Touch.Phase Move, but how do I know I need these and how do I figure out how to implement Unity API into a C# script?*


*A Third Example would be:  I want to use the phone's rear camera as a background, then present 3d or even 2d billboards in front of it.  Similar to what you see in Pokemon Go.
 - I know I need WebCamTexture...  but what else?* 

How do I figure out what pieces I need, then how to apply them?

How should I think, logically, to accomplish these tasks?

Even if one understands the basic fundamentals of C#, like methods, variables, bools, etc, – How does one learn to build, write, and structure the code accordingly?

Can anyone break this process down into layman terms?

The answer is always the same, no matter how someone asks this question: Test-driven development.

Decompose your requirements into individual behaviors, codify them as falsifiable claims about your system that you can use to determine whether or not your system has a particular behavior, if possible (which is almost always the case), translate those claims into tests, see them fail, and then make them pass.

A great way to make falsifiable claims is using the given-when-then syntax associated with Gherkin runners like SpecFlow. You define all of the relevant details about the state of your system before a behavior executes in the given statements. Then you describe what causes the behavior to be invoked in the when block. Finally, you describe all the relevant details about the state of your system after the behavior had executed in the context defined by the given statements.

Automated tests will connect this product specification with your technical specification and create a context that drives a very natural design. That’s natural to your objectives, rather than to your platform it route workers. That’s okay, that’s what you want: to bend the system to your will rather than to bend your will to the system.

Ideally you’re dealing with one thing at a given level at a time. So you’ll have high-level behaviors (e.g., make a person look like a character from the game) which will beget lower-level behaviors (e.g., each of the following: find all the people on the camera, identify on person as a player, map the person’s pose to the skeleton of the character, instantiate the character and position correctly).

I like Visual Studio for all coffee that doesn’t absolutely need to be coupled to the Unity frameworks. If you have multiple people collaborating and need GWT as a communication medium across skills-sets, you can use SpecFlow to execute your tests but, otherwise, I think it’s more efficient to just write them yourself using NUnit or MSTest.

Okay. This is a tall order, especially if you want things to stay in layperson terms.

I’ll take your three questions one at a time:

How do I figure out what pieces I need, then how to apply them?

This is the one that’s really hard to understand. Your best bet is recursive searches. That is: a series of searches where the outcome of each search is to identify a better set of search terms.

For things like programming-language syntax and basic programming, you can use a tool like hackerrank.com. They’ll put you through a series of coding challenges, starting with the iconic “Hello, World” exercise and, game-by-game walk you through to some degree of programming competency.

For the .NET framework (the broad system of tools defined by Microsoft’s .NET platform, much of which is available in Unity), you can use msdn.microsoft.com (the Microsoft Developer Network, basically it has evolved into Microsoft’s documentation suite for developers). For the Unity framework (the special stuff, which is not a part of .NET that Unity offers to programmers), you can use docs.unity3d.com. That said, Google’s search is better and broader if you don’t know what you seek. Just ask your question, learn a little bit of jargon, ask a better question, learn a little bit of jargon, et cetera.

How should I think, logically, to accomplish these tasks?

Design Patterns help people think about their problems in a design-friendly way. The problem is that most of the books on Design Patterns are pretty technically focused. You might want to lay some groundwork with Alexander’s A Timeless Way of Building while you teach yourself the basics of coding. Then, once you understand things like classes, methods, et cetera, you’ll have a nice foundation of cross-domain knowledge about design that can be applied to learning Design Patterns as we think of them in the software development industry.

Design Patterns give you good analytical tools for decomposing large, intractable-seeming problems into many small ones. I still think that ATDD is a great way to focus your efforts, though, because it drives your whole design and development process from the outcomes you want to see rather than from technical details.

So, you start by defining an high-level behavior, such as the following (my best guess at your first requirement):

Scenario: Keep an object's position fixed r
Given a phone with a camera and a gyroscope
And an augmented-reality object (O) visible on the camera
And O's "up" is visually aligned with the user's up
And O is being touched
When the phone is rotated 90-degrees clockwise
Then O's "up" is visually aligned with the user's right

From that, you can identify a litany of other “sub” behaviors, by asking yourself what you need to do to make it happen:

  • How do I know that an object is visible on the camera?
  • How do I detect the rotation?
  • How do I rotate the object?
  • How do I detect the object is being touched?
  • How do I stop rotating the object?
  • et cetera

Each of these things will drive your analysis and decomposition efforts further and help you organize what needs to be done while defining how you will tell that it actually is done.

Keep in mind that it doesn’t matter if that’s the right definition of your requirement. It’s just an example of a non-controversial definition of a behavior: everyone who sees it at any point in time is going to interpret the behavior of a system to either match that description or violate it the same way.

So, as a developer, you need to familiarize yourself with Design Patterns (along with the basics like syntax and code quality) and as a product designer, you need to familiarize yourself with ATDD. As I’ve said in my comment, Unit-Test-Driven Development will help you evolve your designs over time but let’s just keep the most important things in focus, for now.

Even if one understands the basic fundamentals of C#, like methods, variables, bools, etc, – How does one learn to build, write, and structure the code accordingly?

Um. Practice? I mean. There are guidelines. For instance: everything should be kept as private as possible until you have a reason to make it more public. These are just a starting point. You’re going to have to practice, practice, and then practice some more. Over time, you will incorporate these guidelines into your process, then into your thinking, and then they will become something you do instinctively.

The number of things that are available to learn is vast. Depending on your rate of absorption, you could spend years or even decades studying them all. So don’t bother trying to learn everything. Just pick the few most important things: Syntax, Code Quality, and the parts of the Unity and .NET Frameworks you absolutely need to accomplish your objectives. Get good those things and, when you are comfortable with them - when there is almost no chance that you will abandon them if the going gets tough - add one or two more. Repeat that process until you are writing these answers for the next generation of programmers.

Sorry I can’t give you a simpler, more concise answer but you basically asked “How do I get good at something that some people choose as a life’s work.” The simple answer isn’t any more comforting than the long one: Make it your life’s work.

Failing that, make it your most prominent hobby.

To touch an object and have it follow the camera, I just temporarily make that object a Child of the Main Camera
using UnityEngine;
using System.Collections;

public class DragHandler : MonoBehaviour
{
    private Ray m_Ray;
    private RaycastHit m_RayCastHit;
    private Collider m_CurrentMovableObject;
    private float m_MovementMultipier = 0.4f;


    void Update()
    {
        if (Input.touchCount == 1)
        {
            Touch touchedFinger = Input.touches[0];

            switch (touchedFinger.phase)
            {
                case TouchPhase.Began:
                    m_Ray = Camera.main.ScreenPointToRay(touchedFinger.position);  //gets the touch position
                    if (Physics.Raycast(m_Ray.origin, m_Ray.direction, out m_RayCastHit, Mathf.Infinity))
                    {
                        Collider movableObj = m_RayCastHit.collider.gameObject.GetComponent<Collider>();
                        if (movableObj)
                        {
                            m_CurrentMovableObject = movableObj;
                            m_CurrentMovableObject.transform.parent = Camera.main.transform;
                        }
                    }
                    break;
                case TouchPhase.Moved:  //move the object when finger moves.
                    if (m_CurrentMovableObject)
                    {
                        m_CurrentMovableObject.gameObject.transform.Translate(Time.deltaTime * m_MovementMultipier *
                            new Vector3(-touchedFinger.deltaPosition.x, touchedFinger.deltaPosition.y, 0));
                    }
                    break;
                case TouchPhase.Ended:
                    if (m_CurrentMovableObject != null)
                    {
                        m_CurrentMovableObject.transform.parent = null;
                    }
                    m_CurrentMovableObject = null;
                    break;
                default:
                    break;
            }
        }

        if (Input.touchCount == 2)
        {
            // Store both touches.
            Touch touchZero = Input.touches[0];
            Touch touchOne = Input.GetTouch(1);
            float speed = 0.01f;

            // Find the position in the previous frame of each touch.
            Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
            Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;

            // Find the magnitude of the vector (the distance) between the touches in each frame.
            float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude;
            float touchDeltaMag = (touchZero.position - touchOne.position).magnitude;

            // Find the difference in the distances between each frame.
            float deltaMagnitudeDiff = prevTouchDeltaMag - touchDeltaMag;

            
            switch (touchZero.phase)
            {
                case TouchPhase.Began:
                    m_Ray = Camera.main.ScreenPointToRay(touchZero.position);
                    if (Physics.Raycast(m_Ray.origin, m_Ray.direction, out m_RayCastHit, Mathf.Infinity))
                    {
                        Collider movableObj = m_RayCastHit.collider.gameObject.GetComponent<BoxCollider>();
                        if (movableObj)
                        {
                            m_CurrentMovableObject = movableObj;
                            movableObj.transform.parent = Camera.main.transform;
                        }
                    }
                    break;

                case TouchPhase.Moved:
                    if (m_CurrentMovableObject)
                    {
                        m_CurrentMovableObject.transform.Translate(0, 0, -deltaMagnitudeDiff * speed);
                    }
                    break;

                case TouchPhase.Ended:
                    if (m_CurrentMovableObject != null)
                    {
                        m_CurrentMovableObject.transform.parent = null;
                    }
                    m_CurrentMovableObject = null;
                    break;
            }
        } 
    }
}

Then I had an issue of it not facing the camera as I rotate the Gyroscope, so I attached this script to the Movable Object.

using UnityEngine;

public class MovableObject : MonoBehaviour
{
    private void Update()
    {
        transform.LookAt(Camera.main.transform);
    }
}